diff --git a/bindings/go/osvschema/constants.go b/bindings/go/osvschema/constants.go index 9462838f..b8d45743 100644 --- a/bindings/go/osvschema/constants.go +++ b/bindings/go/osvschema/constants.go @@ -17,6 +17,7 @@ const ( EcosystemCRAN Ecosystem = "CRAN" EcosystemCratesIO Ecosystem = "crates.io" EcosystemDebian Ecosystem = "Debian" + EcosystemDrupal Ecosystem = "Drupal" EcosystemGHC Ecosystem = "GHC" EcosystemGitHubActions Ecosystem = "GitHub Actions" EcosystemGo Ecosystem = "Go" diff --git a/docs/schema.md b/docs/schema.md index 34628c7b..6c25e5df 100644 --- a/docs/schema.md +++ b/docs/schema.md @@ -245,6 +245,17 @@ The defined database prefixes and their "home" databases are: + + DRUPAL + Drupal Advisory Database (provided by Ackama) + + + + ELA Debian Extended LTS Security Advisories (provided by Freexian) @@ -790,6 +801,7 @@ The defined ecosystems are: | `CRAN` | The R package ecosystem. The `name` is an R package name. | | `crates.io` | The crates.io ecosystem for Rust; the `name` field is a crate name. | | `Debian` | The Debian package ecosystem; the `name` is the name of the source package. The ecosystem string might optionally have a `:` suffix to scope the package to a particular Debian release. `` is a numeric version specified in the [Debian distro-info-data](https://debian.pages.debian.net/distro-info-data/debian.csv). For example, the ecosystem string "Debian:7" refers to the Debian 7 (wheezy) release. | +| `Drupal` | The Drupal CMS ecosystem, for packages sourced from the Drupal composer repository. The ecosystem implies https://packages.drupal.org/8 as the source repository, unless a :7 suffix is present in which case the repository is https://packages.drupal.org/7 | | `GHC` | The Haskell compiler ecosystem. The `name` field is the name of a component of the GHC compiler ecosystem (e.g., compiler, GHCI, RTS). | | `GitHub Actions` | The GitHub Actions ecosystem; the `name` field is the action's repository name with owner e.g. `{owner}/{repo}`. | | `Go` | The Go ecosystem; the `name` field is a Go module path. | diff --git a/ecosystems.json b/ecosystems.json index c5fb7ce1..547bb4ff 100644 --- a/ecosystems.json +++ b/ecosystems.json @@ -11,6 +11,7 @@ "CRAN": "The R package ecosystem. The `name` is an R package name.", "crates.io": "The crates.io ecosystem for Rust; the `name` field is a crate name.", "Debian": "The Debian package ecosystem; the `name` is the name of the source package. The ecosystem string might optionally have a `:` suffix to scope the package to a particular Debian release. `` is a numeric version specified in the [Debian distro-info-data](https://debian.pages.debian.net/distro-info-data/debian.csv). For example, the ecosystem string \"Debian:7\" refers to the Debian 7 (wheezy) release.", + "Drupal": "The Drupal CMS ecosystem, for packages sourced from the Drupal composer repository. The ecosystem implies https://packages.drupal.org/8 as the source repository, unless a :7 suffix is present in which case the repository is https://packages.drupal.org/7", "GHC": "The Haskell compiler ecosystem. The `name` field is the name of a component of the GHC compiler ecosystem (e.g., compiler, GHCI, RTS).", "GitHub Actions": "The GitHub Actions ecosystem; the `name` field is the action's repository name with owner e.g. `{owner}/{repo}`.", "Go": "The Go ecosystem; the `name` field is a Go module path.", diff --git a/tools/osv-linter/internal/checks/packages.go b/tools/osv-linter/internal/checks/packages.go index c8358e80..130d77c1 100644 --- a/tools/osv-linter/internal/checks/packages.go +++ b/tools/osv-linter/internal/checks/packages.go @@ -37,9 +37,14 @@ func PackageExists(json *gjson.Result, config *Config) (findings []CheckError) { if !maybePackage.Exists() { return true // keep iterating (over affected entries) } - // Normalize ecosystems with a colon to their base. + ecosystem := value.Get("package.ecosystem").String() + + // Normalize ecosystems with a colon to their base, except for the Drupal ecosystem + // as different repositories are used depending on the suffix // e.g. "Alpine:v3.5" -> "Alpine" - ecosystem := strings.Split(value.Get("package.ecosystem").String(), ":")[0] + if !strings.HasPrefix(ecosystem, "Drupal") { + ecosystem = strings.Split(ecosystem, ":")[0] + } // Use config.Ecosystems as an allowlist, if it is set. if len(config.Ecosystems) > 0 && !slices.Contains(config.Ecosystems, ecosystem) { return true // keep iterating (over affected entries) diff --git a/tools/osv-linter/internal/checks/schema_generated.json b/tools/osv-linter/internal/checks/schema_generated.json index b30a9ef6..0cea599e 100644 --- a/tools/osv-linter/internal/checks/schema_generated.json +++ b/tools/osv-linter/internal/checks/schema_generated.json @@ -341,6 +341,7 @@ "CRAN", "crates.io", "Debian", + "Drupal", "GHC", "GitHub Actions", "Go", @@ -377,13 +378,13 @@ "type": "string", "title": "Currently supported ecosystems", "description": "These ecosystems are also documented at https://ossf.github.io/osv-schema/#affectedpackage-field", - "pattern": "^(AlmaLinux|Alpaquita|Alpine|Android|BellSoft Hardened Containers|Bioconductor|Bitnami|Chainguard|ConanCenter|CRAN|crates\\.io|Debian|GHC|GitHub Actions|Go|Hackage|Hex|Kubernetes|Linux|Mageia|Maven|MinimOS|npm|NuGet|openEuler|openSUSE|OSS-Fuzz|Packagist|Photon OS|Pub|PyPI|Red Hat|Rocky Linux|RubyGems|SUSE|SwiftURL|Ubuntu|Wolfi|GIT)(:.+)?$" + "pattern": "^(AlmaLinux|Alpaquita|Alpine|Android|BellSoft Hardened Containers|Bioconductor|Bitnami|Chainguard|ConanCenter|CRAN|crates\\.io|Debian|Drupal|GHC|GitHub Actions|Go|Hackage|Hex|Kubernetes|Linux|Mageia|Maven|MinimOS|npm|NuGet|openEuler|openSUSE|OSS-Fuzz|Packagist|Photon OS|Pub|PyPI|Red Hat|Rocky Linux|RubyGems|SUSE|SwiftURL|Ubuntu|Wolfi|GIT)(:.+)?$" }, "prefix": { "type": "string", "title": "Currently supported home database identifier prefixes", "description": "These home databases are also documented at https://ossf.github.io/osv-schema/#id-modified-fields", - "pattern": "^(ASB-A|PUB-A|ALSA|ALBA|ALEA|BELL|BIT|CGA|CURL|CVE|DSA|DLA|ELA|DTSA|GHSA|GO|GSD|HSEC|KUBE|LBSEC|LSN|MAL|MINI|MGASA|OESA|OSV|openSUSE-SU|PHSA|PSF|PYSEC|RHBA|RHEA|RHSA|RLSA|RXSA|RSEC|RUSTSEC|SUSE-[SRFO]U|UBUNTU|USN|V8)-" + "pattern": "^(ASB-A|PUB-A|ALSA|ALBA|ALEA|BELL|BIT|CGA|CURL|CVE|DSA|DLA|DRUPAL|ELA|DTSA|GHSA|GO|GSD|HSEC|KUBE|LBSEC|LSN|MAL|MINI|MGASA|OESA|OSV|openSUSE-SU|PHSA|PSF|PYSEC|RHBA|RHEA|RHSA|RLSA|RXSA|RSEC|RUSTSEC|SUSE-[SRFO]U|UBUNTU|USN|V8)-" }, "severity": { "type": [ diff --git a/tools/osv-linter/internal/pkgchecker/ecosystems.go b/tools/osv-linter/internal/pkgchecker/ecosystems.go index 7ff9c99b..c7424d5e 100644 --- a/tools/osv-linter/internal/pkgchecker/ecosystems.go +++ b/tools/osv-linter/internal/pkgchecker/ecosystems.go @@ -13,6 +13,7 @@ var SupportedEcosystems = []string{ "NuGet", "RubyGems", "Packagist", + "Drupal", "Pub", "Hackage", "Maven", @@ -27,6 +28,7 @@ var EcosystemBaseURLs = map[string]string{ "NuGet": "https://api.nuget.org/v3-flatcontainer", "RubyGems": "https://rubygems.org/api/v1/gems", "Packagist": "https://repo.packagist.org/p2", + "Drupal": "https://packages.drupal.org/files/packages/8/p2", "Pub": "https://pub.dev/api/packages", "Hackage": "https://hackage.haskell.org/package", "Maven": "https://search.maven.org/solrsearch/select", @@ -51,6 +53,10 @@ func ExistsInEcosystem(pkg string, ecosystem string) bool { return existsInCrates(pkg) case "Debian": return true + case "Drupal": + return existsInDrupal(pkg) + case "Drupal:7": + return true case "GIT": return true case "GitHub Actions": @@ -136,6 +142,8 @@ func VersionsExistInEcosystem(pkg string, versions []string, ecosystem string) e return nil case "Debian": return nil + case "Drupal": + return nil case "GIT": return nil case "GitHub Actions": diff --git a/tools/osv-linter/internal/pkgchecker/package_check.go b/tools/osv-linter/internal/pkgchecker/package_check.go index 13d2d030..676decb2 100644 --- a/tools/osv-linter/internal/pkgchecker/package_check.go +++ b/tools/osv-linter/internal/pkgchecker/package_check.go @@ -86,6 +86,13 @@ func existsInPackagist(pkg string) bool { return checkPackageExists(packageInstanceURL) } +// Validate the existence of a package in Packagist. +func existsInDrupal(pkg string) bool { + packageInstanceURL := fmt.Sprintf("%s/%s.json", EcosystemBaseURLs["Drupal"], pkg) + + return checkPackageExists(packageInstanceURL) +} + // Validate the existence of a package in PyPI. func existsInPyPI(pkg string) bool { ecosystem := "PyPI" diff --git a/tools/osv-linter/internal/pkgchecker/package_check_test.go b/tools/osv-linter/internal/pkgchecker/package_check_test.go index 809bf71b..e1f44756 100644 --- a/tools/osv-linter/internal/pkgchecker/package_check_test.go +++ b/tools/osv-linter/internal/pkgchecker/package_check_test.go @@ -144,6 +144,33 @@ func Test_existsInPackagist(t *testing.T) { } } +func Test_existsInDrupal(t *testing.T) { + tests := []struct { + name string + pkg string + want bool + ver string + }{ + { + name: "existing package", + pkg: "drupal/tfa", + want: true, + }, + { + name: "non-existing package", + pkg: "non-existing-package", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := existsInDrupal(tt.pkg); got != tt.want { + t.Errorf("existsInDrupal() = %v, want %v", got, tt.want) + } + }) + } +} + func Test_existsInPub(t *testing.T) { tests := []struct { name string diff --git a/validation/schema.json b/validation/schema.json index b30a9ef6..0cea599e 100644 --- a/validation/schema.json +++ b/validation/schema.json @@ -341,6 +341,7 @@ "CRAN", "crates.io", "Debian", + "Drupal", "GHC", "GitHub Actions", "Go", @@ -377,13 +378,13 @@ "type": "string", "title": "Currently supported ecosystems", "description": "These ecosystems are also documented at https://ossf.github.io/osv-schema/#affectedpackage-field", - "pattern": "^(AlmaLinux|Alpaquita|Alpine|Android|BellSoft Hardened Containers|Bioconductor|Bitnami|Chainguard|ConanCenter|CRAN|crates\\.io|Debian|GHC|GitHub Actions|Go|Hackage|Hex|Kubernetes|Linux|Mageia|Maven|MinimOS|npm|NuGet|openEuler|openSUSE|OSS-Fuzz|Packagist|Photon OS|Pub|PyPI|Red Hat|Rocky Linux|RubyGems|SUSE|SwiftURL|Ubuntu|Wolfi|GIT)(:.+)?$" + "pattern": "^(AlmaLinux|Alpaquita|Alpine|Android|BellSoft Hardened Containers|Bioconductor|Bitnami|Chainguard|ConanCenter|CRAN|crates\\.io|Debian|Drupal|GHC|GitHub Actions|Go|Hackage|Hex|Kubernetes|Linux|Mageia|Maven|MinimOS|npm|NuGet|openEuler|openSUSE|OSS-Fuzz|Packagist|Photon OS|Pub|PyPI|Red Hat|Rocky Linux|RubyGems|SUSE|SwiftURL|Ubuntu|Wolfi|GIT)(:.+)?$" }, "prefix": { "type": "string", "title": "Currently supported home database identifier prefixes", "description": "These home databases are also documented at https://ossf.github.io/osv-schema/#id-modified-fields", - "pattern": "^(ASB-A|PUB-A|ALSA|ALBA|ALEA|BELL|BIT|CGA|CURL|CVE|DSA|DLA|ELA|DTSA|GHSA|GO|GSD|HSEC|KUBE|LBSEC|LSN|MAL|MINI|MGASA|OESA|OSV|openSUSE-SU|PHSA|PSF|PYSEC|RHBA|RHEA|RHSA|RLSA|RXSA|RSEC|RUSTSEC|SUSE-[SRFO]U|UBUNTU|USN|V8)-" + "pattern": "^(ASB-A|PUB-A|ALSA|ALBA|ALEA|BELL|BIT|CGA|CURL|CVE|DSA|DLA|DRUPAL|ELA|DTSA|GHSA|GO|GSD|HSEC|KUBE|LBSEC|LSN|MAL|MINI|MGASA|OESA|OSV|openSUSE-SU|PHSA|PSF|PYSEC|RHBA|RHEA|RHSA|RLSA|RXSA|RSEC|RUSTSEC|SUSE-[SRFO]U|UBUNTU|USN|V8)-" }, "severity": { "type": [