-
Notifications
You must be signed in to change notification settings - Fork 865
Draft: add BellSoft family of OS #3264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
90d027e
f289de3
e55bb38
353d7ee
09e6883
b17e6fd
76aa9f2
2cddf53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| { | ||
| "affected": [ | ||
| { | ||
| "package": { | ||
| "ecosystem": "Alpaquita:23", | ||
| "name": "expat", | ||
| "purl": "pkg:apk/alpaquita/expat?arch=source&distro=23" | ||
| }, | ||
| "ranges": [ | ||
| { | ||
| "events": [ | ||
| { | ||
| "introduced": "2.5.0-r0" | ||
| }, | ||
| { | ||
| "fixed": "2.7.2-r0" | ||
| } | ||
| ], | ||
| "type": "ECOSYSTEM" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "package": { | ||
| "ecosystem": "Alpaquita:25", | ||
| "name": "expat", | ||
| "purl": "pkg:apk/alpaquita/expat?arch=source&distro=25" | ||
| }, | ||
| "ranges": [ | ||
| { | ||
| "events": [ | ||
| { | ||
| "introduced": "2.7.1-r0" | ||
| }, | ||
| { | ||
| "fixed": "2.7.2-r0" | ||
| } | ||
| ], | ||
| "type": "ECOSYSTEM" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "package": { | ||
| "ecosystem": "Alpaquita:stream", | ||
| "name": "expat", | ||
| "purl": "pkg:apk/alpaquita/expat?arch=source&distro=stream" | ||
| }, | ||
| "ranges": [ | ||
| { | ||
| "events": [ | ||
| { | ||
| "introduced": "2.4.9-r0" | ||
| }, | ||
| { | ||
| "fixed": "2.7.2-r0" | ||
| } | ||
| ], | ||
| "type": "ECOSYSTEM" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "package": { | ||
| "ecosystem": "BellSoft Hardened Containers:23", | ||
| "name": "expat", | ||
| "purl": "pkg:apk/bellsoft-hardened-containers/expat?arch=source&distro=23" | ||
| }, | ||
| "ranges": [ | ||
| { | ||
| "events": [ | ||
| { | ||
| "introduced": "2.5.0-r0" | ||
| }, | ||
| { | ||
| "fixed": "2.7.2-r0" | ||
| } | ||
| ], | ||
| "type": "ECOSYSTEM" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "package": { | ||
| "ecosystem": "BellSoft Hardened Containers:25", | ||
| "name": "expat", | ||
| "purl": "pkg:apk/bellsoft-hardened-containers/expat?arch=source&distro=25" | ||
| }, | ||
| "ranges": [ | ||
| { | ||
| "events": [ | ||
| { | ||
| "introduced": "2.7.1-r0" | ||
| }, | ||
| { | ||
| "fixed": "2.7.2-r0" | ||
| } | ||
| ], | ||
| "type": "ECOSYSTEM" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "package": { | ||
| "ecosystem": "BellSoft Hardened Containers:stream", | ||
| "name": "expat", | ||
| "purl": "pkg:apk/bellsoft-hardened-containers/expat?arch=source&distro=stream" | ||
| }, | ||
| "ranges": [ | ||
| { | ||
| "events": [ | ||
| { | ||
| "introduced": "2.4.9-r0" | ||
| }, | ||
| { | ||
| "fixed": "2.7.2-r0" | ||
| } | ||
| ], | ||
| "type": "ECOSYSTEM" | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "id": "BELL-CVE-2025-59375", | ||
| "modified": "2025-12-23T13:05:51.859654Z", | ||
| "published": "2025-09-15T11:56:23.866967Z", | ||
| "references": [ | ||
| { | ||
| "type": "ADVISORY", | ||
| "url": "https://docs.bell-sw.com/security/cves/CVE-2025-59375" | ||
| }, | ||
| { | ||
| "type": "ADVISORY", | ||
| "url": "https://docs.bell-sw.com/security/advisories/BELL-SA-2025-13" | ||
| } | ||
| ], | ||
| "schema_version": "1.7.4", | ||
| "severity": [ | ||
| { | ||
| "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", | ||
| "type": "CVSS_V3" | ||
| } | ||
| ], | ||
| "upstream": [ | ||
| "CVE-2025-59375" | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| package osv | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "sort" | ||
| "strings" | ||
|
|
||
| "github.com/google/osv-scanner/pkg/models" | ||
|
|
||
| "github.com/anchore/grype/grype/db/data" | ||
| "github.com/anchore/grype/grype/db/internal/provider/unmarshal" | ||
| "github.com/anchore/grype/grype/db/provider" | ||
| db "github.com/anchore/grype/grype/db/v6" | ||
| "github.com/anchore/grype/grype/db/v6/build/transformers" | ||
| "github.com/anchore/grype/grype/db/v6/build/transformers/internal" | ||
| "github.com/anchore/grype/grype/db/v6/name" | ||
| "github.com/anchore/syft/syft/pkg" | ||
| ) | ||
|
|
||
| // bellsoftStrategy handles BELL-* records from BellSoft's vulnerability database. | ||
| // BellSoft records describe *affected* version ranges of upstream components | ||
| // (apache, node, spark, etc.) packaged by BellSoft. | ||
| // | ||
| // BellSoft-specific decisions: | ||
| // - CVE refs are in `upstream` field | ||
| // - Package type comes from the PURL (always present, e.g. pkg:apk/alpaquita/apache). | ||
| // - Ecosystem stays as "BellSoft" — there is no underlying distro. | ||
| // - No qualifiers are emitted. `database_specific.cpes` is intentionally | ||
| // dropped: the bellsoft matcher never queries by CPE, the platform CPE | ||
| // qualifier is a runtime no-op for application CPEs, and CPEs without | ||
| // ecosystem context produce noisy matches. | ||
| type bellsoftStrategy struct{} | ||
|
|
||
| func (bellsoftStrategy) Matches(id string) bool { | ||
| return strings.HasPrefix(id, "BELL-") | ||
| } | ||
|
|
||
| func (bellsoftStrategy) Transform(vuln unmarshal.OSVVulnerability, state provider.State) ([]data.Entry, error) { | ||
|
willmurphyscode marked this conversation as resolved.
|
||
| severities, err := getSeverities(vuln) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("unable to obtain severities: %w", err) | ||
| } | ||
|
|
||
| in := []any{ | ||
| db.VulnerabilityHandle{ | ||
| Name: vuln.ID, | ||
| ProviderID: state.Provider, | ||
| Provider: provider.Model(state), | ||
| Status: db.VulnerabilityActive, | ||
| ModifiedDate: &vuln.Modified, | ||
| PublishedDate: &vuln.Published, | ||
| BlobValue: &db.VulnerabilityBlob{ | ||
| ID: vuln.ID, | ||
| Description: vuln.Details, | ||
| References: bellsoftReferences(vuln), | ||
| Aliases: vuln.Aliases, | ||
| Severities: severities, | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| for _, aph := range bellsoftAffectedPackages(vuln) { | ||
| in = append(in, aph) | ||
| } | ||
| return transformers.NewEntries(in...), nil | ||
| } | ||
|
|
||
| func bellsoftReferences(vuln unmarshal.OSVVulnerability) []db.Reference { | ||
| var refs []db.Reference | ||
| for _, ref := range vuln.References { | ||
| refs = append(refs, db.Reference{ | ||
| URL: ref.URL, | ||
| Tags: []string{string(ref.Type)}, | ||
| }) | ||
| } | ||
| return refs | ||
| } | ||
|
|
||
| func bellsoftAffectedPackages(vuln unmarshal.OSVVulnerability) []db.AffectedPackageHandle { | ||
| if len(vuln.Affected) == 0 { | ||
| return nil | ||
| } | ||
| var aphs []db.AffectedPackageHandle | ||
| for _, affected := range vuln.Affected { | ||
| var ranges []db.Range | ||
| for _, r := range affected.Ranges { | ||
| ranges = append(ranges, getGrypeRangesFromRange(r, bellsoftRangeType(r.Type))...) | ||
| } | ||
| aphs = append(aphs, db.AffectedPackageHandle{ | ||
| Package: bellsoftPackage(affected.Package), | ||
| BlobValue: &db.PackageBlob{ | ||
| CVEs: vuln.Aliases, // FIXME: should be `vuln.Upstream` | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand this comment. Can you elaborate a bit?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure. |
||
| Ranges: ranges, | ||
| }, | ||
| }) | ||
| } | ||
| sort.Sort(internal.ByAffectedPackage(aphs)) | ||
| return aphs | ||
| } | ||
|
|
||
| func bellsoftPackage(p models.Package) *db.Package { | ||
| pkgType := pkg.TypeFromPURL(p.Purl) | ||
| return &db.Package{ | ||
| Ecosystem: string(p.Ecosystem), | ||
| Name: name.Normalize(p.Name, pkgType), | ||
| } | ||
| } | ||
|
|
||
| // bellsoftRangeType maps an OSV range type to the grype version-format string | ||
| // for BellSoft records. SEMVER ranges describe apk-flavored semver | ||
| // (separate version comparator); other OSV types fall through to the default. | ||
| func bellsoftRangeType(t models.RangeType) string { | ||
| if t == models.RangeSemVer { | ||
| return "apk" | ||
| } | ||
| return defaultRangeType(t) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,8 @@ const ( | |
| CentOS Type = "centos" | ||
| Fedora Type = "fedora" | ||
| Alpine Type = "alpine" | ||
| Alpaquita Type = "alpaquita" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you help me understand the relationship between alpaquita and bellsoft hardened containers? It looks like they're both in OSV but with overlap and the same vendor prefix? https://osv.dev/list?ecosystem=Alpaquita and https://osv.dev/list?ecosystem=BellSoft+Hardened+Containers ? It looks like their two different distros and we should just model them as two different distros, and their relationship is just that the same company works on them?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| BellSoftHardenedContainers Type = "bellsoft-hardened-containers" | ||
| Busybox Type = "busybox" | ||
| AmazonLinux Type = "amazonlinux" | ||
| OracleLinux Type = "oraclelinux" | ||
|
|
@@ -48,6 +50,8 @@ var All = []Type{ | |
| CentOS, | ||
| Fedora, | ||
| Alpine, | ||
| Alpaquita, | ||
| BellSoftHardenedContainers, | ||
| Busybox, | ||
| AmazonLinux, | ||
| OracleLinux, | ||
|
|
@@ -80,6 +84,8 @@ var IDMapping = map[string]Type{ | |
| "centos": CentOS, | ||
| "fedora": Fedora, | ||
| "alpine": Alpine, | ||
| "alpaquita": Alpaquita, | ||
| "bellsoft-hardened-containers": BellSoftHardenedContainers, | ||
| "busybox": Busybox, | ||
| "amzn": AmazonLinux, | ||
| "ol": OracleLinux, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change isn't correct, for example you can see it breaks unit tests for another OSV provider: https://github.com/anchore/grype/actions/runs/25853467114/job/76529191535?pr=3264#step:4:108
I think the arguments passed to
AndConstraintare wrong in the BellSoft case?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is to fix anchore/vunnel#924 (comment)
The fix is incomplete/incorrect and need to be fixed in its order.