Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pkg/vulnsrc/alpine/alpine.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ func (vs VulnSrc) saveSecFixes(tx *bolt.Tx, platform, pkgName string, secfixes m
ids := strings.Fields(vulnID)
for _, cveID := range ids {
cveID = strings.ReplaceAll(cveID, "CVE_", "CVE-")
if !strings.HasPrefix(cveID, "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 {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm not wrong, I found two issues with the current implementation:

  1. 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) > 1 and the first ID doesn't
      start with "CVE-", the GHSA ID gets skipped
  2. 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"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's good news. But advisories often contain invalid or unreliable data, so it's best to filter out anything that's obviously incorrect.

continue
}
if err := vs.dbc.PutAdvisoryDetail(tx, cveID, pkgName, []string{platform}, advisory); err != nil {
Expand Down
60 changes: 60 additions & 0 deletions pkg/vulnsrc/alpine/alpine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,72 @@ func TestVulnSrc_Update(t *testing.T) {
FixedVersion: "2.9.3-r0",
},
},
{
Key: []string{"advisory-detail", "CVE-2024-22195", "alpine 3.12", "ansible"},
Value: types.Advisory{
FixedVersion: "2.9.3-r0",
},
},
{
Key: []string{"advisory-detail", "CVE-2017-2616", "alpine 3.12", "ansible"},
Value: types.Advisory{
FixedVersion: "2.9.3-r0",
},
},
{
Key: []string{"advisory-detail", "GHSA-f7r5-w49x-gxm3", "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{
FixedVersion: "2.9.6-r0",
},
},
{
Key: []string{
"vulnerability-id",
"CVE-2019-14904",
},
Value: map[string]interface{}{},
},
{
Key: []string{
"vulnerability-id",
"CVE-2019-14905",
},
Value: map[string]interface{}{},
},
{
Key: []string{
"vulnerability-id",
"CVE-2024-22195",
},
Value: map[string]interface{}{},
},
{
Key: []string{
"vulnerability-id",
"CVE-2017-2616",
},
Value: map[string]interface{}{},
},
{
Key: []string{
"vulnerability-id",
"GHSA-f7r5-w49x-gxm3",
},
Value: map[string]interface{}{},
},
{
Key: []string{
"vulnerability-id",
"CVE-2020-1737",
},
Value: map[string]interface{}{},
},
},
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"secfixes": {
"2.9.3-r0": [
"CVE-2019-14904",
"CVE-2019-14905"
"CVE-2019-14905",
"CVE-2024-22195 GHSA-h5c8-rqwp-cp95",
"CVE-2017-2616 (+ regression fix)",
"GHSA-f7r5-w49x-gxm3"
],
"2.9.6-r0": [
"CVE-2020-1737"
Expand Down