Skip to content

Commit c1b7b8a

Browse files
authored
feat(parser): set fix_available on GitHub Vulnerability findings (#14943)
Populate fix_available from firstPatchedVersion in the GraphQL response.
1 parent 5ce0657 commit c1b7b8a

4 files changed

Lines changed: 86 additions & 0 deletions

File tree

docs/content/supported_tools/parsers/file/github_vulnerability.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ vulnerabilityAlerts (RepositoryVulnerabilityAlert object)
2121
+ severity (CRITICAL/HIGH/LOW/MODERATE)
2222
+ package (optional)
2323
+ name (optional)
24+
+ firstPatchedVersion (optional, sets fix_available)
25+
+ identifier (optional)
2426
+ advisory (SecurityAdvisory object)
2527
+ description
2628
+ summary

dojo/tools/github_vulnerability/parser.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ def get_findings(self, filename, test):
8383
pkg = vuln.get("package", {})
8484
finding.component_name = pkg.get("name")
8585

86+
first_patched = vuln.get("firstPatchedVersion")
87+
finding.fix_available = (
88+
first_patched is not None
89+
and first_patched.get("identifier") is not None
90+
)
91+
8692
if alert.get("createdAt"):
8793
finding.date = dateutil.parser.parse(alert.get("createdAt"))
8894
if alert.get("state") in {"FIXED", "DISMISSED"}:
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"data": {
3+
"repository": {
4+
"vulnerabilityAlerts": {
5+
"nodes": [
6+
{
7+
"id": "RVA_kwDOLJyUo88AAAABNoFixAv",
8+
"createdAt": "2024-03-15T10:00:00Z",
9+
"vulnerableManifestPath": "app/package.json",
10+
"dependabotUpdate": null,
11+
"securityVulnerability": {
12+
"severity": "HIGH",
13+
"updatedAt": "2024-03-10T12:00:00Z",
14+
"package": {
15+
"name": "example-package",
16+
"ecosystem": "NPM"
17+
},
18+
"firstPatchedVersion": null,
19+
"vulnerableVersionRange": "<= 2.0.0",
20+
"advisory": {
21+
"description": "Example vulnerability with no fix available yet.",
22+
"summary": "Prototype pollution in example-package",
23+
"identifiers": [
24+
{
25+
"value": "GHSA-test-no-fix",
26+
"type": "GHSA"
27+
},
28+
{
29+
"value": "CVE-2024-99999",
30+
"type": "CVE"
31+
}
32+
],
33+
"references": [
34+
{
35+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-99999"
36+
}
37+
],
38+
"cvss": {
39+
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N"
40+
}
41+
}
42+
},
43+
"state": "OPEN",
44+
"vulnerableManifestFilename": "package.json",
45+
"vulnerableRequirements": "= 1.5.0",
46+
"number": 42,
47+
"dependencyScope": "RUNTIME",
48+
"dismissComment": null,
49+
"dismissReason": null,
50+
"dismissedAt": null,
51+
"fixedAt": null
52+
}
53+
]
54+
},
55+
"url": "https://github.com/example-org/example-repo"
56+
}
57+
}
58+
}

unittests/tools/test_github_vulnerability_parser.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,26 @@ def test_parser_version(self):
313313
self.assertEqual(finding.component_version, "5.3.29")
314314
self.assertAlmostEqual(finding.epss_score, 0.00212, places=5)
315315
self.assertAlmostEqual(finding.epss_percentile, 0.44035, places=5)
316+
self.assertTrue(finding.fix_available)
317+
318+
def test_parse_no_fix_available(self):
319+
"""Finding with null firstPatchedVersion should have fix_available=False"""
320+
with (get_unit_tests_scans_path("github_vulnerability") / "github-1-vuln-no-fix.json").open(
321+
encoding="utf-8",
322+
) as testfile:
323+
parser = GithubVulnerabilityParser()
324+
findings = parser.get_findings(testfile, Test())
325+
self.assertEqual(1, len(findings))
326+
for finding in findings:
327+
finding.clean()
328+
329+
with self.subTest(i=0):
330+
finding = findings[0]
331+
self.assertEqual(finding.title, "Prototype pollution in example-package")
332+
self.assertEqual(finding.severity, "High")
333+
self.assertEqual(finding.component_name, "example-package")
334+
self.assertEqual(finding.component_version, "1.5.0")
335+
self.assertFalse(finding.fix_available)
316336

317337
def test_parse_file_issue_9582(self):
318338
with (get_unit_tests_scans_path("github_vulnerability") / "issue_9582.json").open(encoding="utf-8") as testfile:

0 commit comments

Comments
 (0)