fix(alpine): save not only CVE-IDs#532
Conversation
|
Interesting. Those GHSA-IDs have CVE-IDs. I'm wondering why they prefer GHSA-IDs. |
|
I asked about it - https://gitlab.alpinelinux.org/alpine/security/secdb/-/issues/11 but as we know - a decrease in MITRE funding can lead to a delay between the appearance of a vulnerability (in this case, when the vulnerability is registered on GitHub (assigned an GHSA-ID)) and the moment when this vulnerability is assigned a CVE-ID. |
|
@knqyf263 Alpine answered my question - https://gitlab.alpinelinux.org/alpine/aports/-/issues/17193#note_511802 So I think that such cases will arise, so we can add GHSA-IDS, but when Alpine updates CVE-ID - we will update advisory. |
| // Possible cases when vulnID contains only one non-CVE-ID | ||
| // e.g. only GHSA-ID | ||
| // cf. https://github.com/aquasecurity/vuln-list/blob/a830a1cc031f51a29a1a6f1c28d8366bbb5e7b64/alpine/3.21/community/vaultwarden.json#L9-L13 | ||
| if !strings.HasPrefix(cveID, "CVE-") && len(ids) > 1 { |
There was a problem hiding this comment.
If I'm not wrong, I found two issues with the current implementation:
- Cases like
GHSA-h6cc-rc6q-23j4 (+regression fix)
are not handled correctly- The current logic using
strings.Fields()splits this into["GHSA-h6cc-rc6q-23j4", "(+regression", "fix)"] - Since
len(ids) > 1and the first ID doesn't
start with "CVE-", the GHSA ID gets skipped
- The current logic using
- Comment-only entries like
(+regression_fix)would be incorrectly inserted- If an entry contains only comments without valid vulnerability IDs, the current logic might try to save invalid data
To address these issues, we need to implement stricter parsing that:
- Properly extracts valid vulnerability IDs (CVE-, GHSA-, etc.) regardless of additional text
- Ensures only valid IDs are saved to the database
- Handles edge cases where no valid IDs are present
diff --git a/pkg/vulnsrc/alpine/alpine.go b/pkg/vulnsrc/alpine/alpine.go
index ec7afec..482c196 100644
--- a/pkg/vulnsrc/alpine/alpine.go
+++ b/pkg/vulnsrc/alpine/alpine.go
@@ -97,24 +97,34 @@ func (vs VulnSrc) saveSecFixes(tx *bolt.Tx, platform, pkgName string, secfixes m
for _, vulnID := range vulnIDs {
// See https://gitlab.alpinelinux.org/alpine/infra/docker/secdb/-/issues/3
// e.g. CVE-2017-2616 (+ regression fix)
+ // e.g. GHSA-h6cc-rc6q-23j4 (+regression fix)
ids := strings.Fields(vulnID)
- for _, cveID := range ids {
- cveID = strings.ReplaceAll(cveID, "CVE_", "CVE-")
- // Possible cases when vulnID contains only one non-CVE-ID
- // e.g. only GHSA-ID
- // cf. https://github.com/aquasecurity/vuln-list/blob/a830a1cc031f51a29a1a6f1c28d8366bbb5e7b64/alpine/3.21/community/vaultwarden.json#L9-L13
- if !strings.HasPrefix(cveID, "CVE-") && len(ids) > 1 {
- continue
- }
- if err := vs.dbc.PutAdvisoryDetail(tx, cveID, pkgName, []string{platform}, advisory); err != nil {
- return oops.Wrapf(err, "failed to save advisory")
- }
- // for optimization
- if err := vs.dbc.PutVulnerabilityID(tx, cveID); err != nil {
- return oops.Wrapf(err, "failed to save the vulnerability ID")
+ // Find CVE-ID first, if not found, use GHSA-ID
+ var selectedID string
+ for _, id := range ids {
+ id = strings.ReplaceAll(id, "CVE_", "CVE-")
+ if strings.HasPrefix(id, "CVE-") {
+ selectedID = id
+ break // CVE-ID found, prioritize it
+ } else if strings.HasPrefix(id, "GHSA-") {
+ selectedID = id // Use GHSA-ID if no CVE-ID found yet
}
}
+
+ if selectedID == "" {
+ // No valid vulnerability ID found
+ continue
+ }
+
+ if err := vs.dbc.PutAdvisoryDetail(tx, selectedID, pkgName, []string{platform}, advisory); err != nil {
+ return oops.Wrapf(err, "failed to save advisory")
+ }
+
+ // for optimization
+ if err := vs.dbc.PutVulnerabilityID(tx, selectedID); err != nil {
+ return oops.Wrapf(err, "failed to save the vulnerability ID")
+ }
}
}
return nil
diff --git a/pkg/vulnsrc/alpine/alpine_test.go b/pkg/vulnsrc/alpine/alpine_test.go
index 9f75a6d..58b5ab5 100644
--- a/pkg/vulnsrc/alpine/alpine_test.go
+++ b/pkg/vulnsrc/alpine/alpine_test.go
@@ -59,6 +59,12 @@ func TestVulnSrc_Update(t *testing.T) {
FixedVersion: "2.9.3-r0",
},
},
+ {
+ Key: []string{"advisory-detail", "GHSA-h6cc-rc6q-23j4", "alpine 3.12", "ansible"},
+ Value: types.Advisory{
+ FixedVersion: "2.9.3-r0",
+ },
+ },
{
Key: []string{"advisory-detail", "CVE-2020-1737", "alpine 3.12", "ansible"},
Value: types.Advisory{
@@ -100,6 +106,13 @@ func TestVulnSrc_Update(t *testing.T) {
},
Value: map[string]interface{}{},
},
+ {
+ Key: []string{
+ "vulnerability-id",
+ "GHSA-h6cc-rc6q-23j4",
+ },
+ Value: map[string]interface{}{},
+ },
{
Key: []string{
"vulnerability-id",
diff --git a/pkg/vulnsrc/alpine/testdata/happy/vuln-list/alpine/ansible.json b/pkg/vulnsrc/alpine/testdata/happy/vuln-list/alpine/ansible.json
index 7bd87e9..83be130 100644
--- a/pkg/vulnsrc/alpine/testdata/happy/vuln-list/alpine/ansible.json
+++ b/pkg/vulnsrc/alpine/testdata/happy/vuln-list/alpine/ansible.json
@@ -6,7 +6,8 @@
"CVE-2019-14905",
"CVE-2024-22195 GHSA-h5c8-rqwp-cp95",
"CVE-2017-2616 (+ regression fix)",
- "GHSA-f7r5-w49x-gxm3"
+ "GHSA-f7r5-w49x-gxm3",
+ "GHSA-h6cc-rc6q-23j4 (+regression fix)"
],
"2.9.6-r0": [
"CVE-2020-1737"There was a problem hiding this comment.
It seems that after your issue Alpine did not add invalid data (like `(+regression fix)) to Vuln-ID fields.
And I hope that will not happen
but there can always be errors, so I implemented your idea anyway - 83c3e19
There was a problem hiding this comment.
That's good news. But advisories often contain invalid or unreliable data, so it's best to filter out anything that's obviously incorrect.
Description
There are advisories with a vulnerability ID other than CVE-ID (e.g. GHSA-ID):
e.g. https://security.alpinelinux.org/srcpkg/vaultwarden
So we don't need to save only
CVE-advisories.