Skip to content

Commit 6e974c8

Browse files
committed
Add firstPatchedVersion in github API
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 6ec2e9e commit 6e974c8

14 files changed

Lines changed: 118 additions & 95 deletions

File tree

vulnerabilities/importers/github.py

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from dateutil import parser as dateparser
3131
from django.db.models.query import QuerySet
3232
from packageurl import PackageURL
33+
from univers.version_range import RANGE_CLASS_BY_SCHEMES
3334
from univers.version_range import build_range_from_github_advisory_constraint
3435

3536
from vulnerabilities import severity_systems
@@ -48,6 +49,7 @@
4849
from vulnerabilities.package_managers import VersionAPI
4950
from vulnerabilities.package_managers import get_api_package_name
5051
from vulnerabilities.utils import AffectedPackage as LegacyAffectedPackage
52+
from vulnerabilities.utils import dedupe
5153
from vulnerabilities.utils import get_affected_packages_by_patched_package
5254
from vulnerabilities.utils import get_item
5355
from vulnerabilities.utils import nearest_patched_package
@@ -153,6 +155,9 @@
153155
severity
154156
publishedAt
155157
}
158+
firstPatchedVersion{
159+
identifier
160+
}
156161
package {
157162
name
158163
}
@@ -236,60 +241,64 @@ def process_response(resp: dict, package_type: str) -> Iterable[AdvisoryData]:
236241
return
237242

238243
for vulnerability in vulnerabilities:
244+
aliases = []
239245
affected_packages = []
240-
aliases = set()
241246
github_advisory = get_item(vulnerability, "node")
242247
if not github_advisory:
243248
logger.error(f"No node found in {vulnerability!r}")
244249
continue
245250

246-
name = get_item(github_advisory, "package", "name")
247-
if not name:
248-
logger.error(f"No name found in {github_advisory!r}")
249-
continue
250-
251-
purl = get_purl(pkg_type=package_type, github_name=name)
252-
if not purl:
253-
continue
254-
255-
vulnerable_range = get_item(github_advisory, "vulnerableVersionRange")
256-
if not vulnerable_range:
257-
logger.error(f"No affected range found in {github_advisory!r}")
258-
continue
259-
260-
affected_range = None
261-
try:
262-
affected_range = build_range_from_github_advisory_constraint(
263-
package_type, vulnerable_range
264-
)
265-
except InvalidVersionRange:
266-
logger.error(f"Could not parse affected range {vulnerable_range!r}")
267-
continue
268-
269-
if affected_range != NotImplementedError:
270-
affected_packages.append(
271-
AffectedPackage(
272-
package=purl,
273-
affected_version_range=affected_range,
274-
)
275-
)
276-
277251
advisory = get_item(github_advisory, "advisory")
278252
if not advisory:
279253
logger.error(f"No advisory found in {github_advisory!r}")
280254
continue
281255

256+
summary = get_item(advisory, "summary") or ""
257+
282258
references = get_item(advisory, "references") or []
283259
if references:
284260
urls = (ref["url"] for ref in references)
285261
references = [Reference.from_url(u) for u in urls]
286262

287-
summary = get_item(advisory, "summary")
263+
date_published = get_item(advisory, "publishedAt")
264+
if date_published:
265+
date_published = dateparser.parse(date_published)
266+
267+
name = get_item(github_advisory, "package", "name")
268+
if name:
269+
purl = get_purl(pkg_type=package_type, github_name=name)
270+
if purl:
271+
affected_range = get_item(github_advisory, "vulnerableVersionRange")
272+
fixed_version = get_item(github_advisory, "firstPatchedVersion", "identifier")
273+
if affected_range:
274+
try:
275+
affected_range = build_range_from_github_advisory_constraint(
276+
package_type, affected_range
277+
)
278+
except InvalidVersionRange as e:
279+
logger.error(f"Could not parse affected range {affected_range!r} {e!r}")
280+
affected_range = None
281+
if fixed_version:
282+
try:
283+
fixed_version = RANGE_CLASS_BY_SCHEMES[package_type].version_class(
284+
fixed_version
285+
)
286+
except Exception as e:
287+
logger.error(f"Invalid fixed version {fixed_version!r} {e!r}")
288+
fixed_version = None
289+
if affected_range or fixed_version:
290+
affected_packages.append(
291+
AffectedPackage(
292+
package=purl,
293+
affected_version_range=affected_range,
294+
fixed_version=fixed_version,
295+
)
296+
)
288297
identifiers = get_item(advisory, "identifiers") or []
289298
for identifier in identifiers:
290299
value = identifier["value"]
291300
identifier_type = identifier["type"]
292-
aliases.add(value)
301+
aliases.append(value)
293302
# attach the GHSA with severity score
294303
if identifier_type == "GHSA":
295304
# Each Node has only one GHSA, hence exit after attaching
@@ -310,12 +319,8 @@ def process_response(resp: dict, package_type: str) -> Iterable[AdvisoryData]:
310319
else:
311320
logger.error(f"Unknown identifier type {identifier_type!r} and value {value!r}")
312321

313-
date_published = get_item(advisory, "publishedAt")
314-
if date_published:
315-
date_published = dateparser.parse(date_published)
316-
317322
yield AdvisoryData(
318-
aliases=sorted(list(aliases)),
323+
aliases=dedupe(aliases),
319324
summary=summary,
320325
references=references,
321326
affected_packages=affected_packages,

vulnerabilities/tests/test_data/github_api/composer-expected.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[
22
{
33
"aliases": [
4-
"CVE-2022-0832",
5-
"GHSA-6qcc-whgp-pjj2"
4+
"GHSA-6qcc-whgp-pjj2",
5+
"CVE-2022-0832"
66
],
77
"summary": "Cross-site Scripting in Pimcore",
88
"affected_packages": [
@@ -50,8 +50,8 @@
5050
},
5151
{
5252
"aliases": [
53-
"CVE-2022-0831",
54-
"GHSA-q67f-3jq4-mww2"
53+
"GHSA-q67f-3jq4-mww2",
54+
"CVE-2022-0831"
5555
],
5656
"summary": "Cross-site Scripting in Pimcore",
5757
"affected_packages": [
@@ -99,8 +99,8 @@
9999
},
100100
{
101101
"aliases": [
102-
"CVE-2022-0895",
103-
"GHSA-x28w-hvwc-mp75"
102+
"GHSA-x28w-hvwc-mp75",
103+
"CVE-2022-0895"
104104
],
105105
"summary": "Static Code Injection in Microweber",
106106
"affected_packages": [
@@ -148,8 +148,8 @@
148148
},
149149
{
150150
"aliases": [
151-
"CVE-2022-0589",
152-
"GHSA-gj26-g5qf-jrh7"
151+
"GHSA-gj26-g5qf-jrh7",
152+
"CVE-2022-0589"
153153
],
154154
"summary": "Cross-site Scripting in librenms",
155155
"affected_packages": [
@@ -163,7 +163,7 @@
163163
"subpath": null
164164
},
165165
"affected_version_range": "vers:composer/<22.1.0",
166-
"fixed_version": null
166+
"fixed_version": "22.1.0"
167167
}
168168
],
169169
"references": [

vulnerabilities/tests/test_data/github_api/composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@
150150
"package": {
151151
"name": "librenms/librenms"
152152
},
153+
"firstPatchedVersion": {
154+
"identifier" :"22.1.0"
155+
},
153156
"vulnerableVersionRange": "< 22.1.0"
154157
}
155158
}

vulnerabilities/tests/test_data/github_api/gem-expected.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[
22
{
33
"aliases": [
4-
"CVE-2009-4492",
5-
"GHSA-6mq2-37j5-w6r6"
4+
"GHSA-6mq2-37j5-w6r6",
5+
"CVE-2009-4492"
66
],
77
"summary": "Moderate severity vulnerability that affects webrick",
88
"affected_packages": [
@@ -16,7 +16,7 @@
1616
"subpath": null
1717
},
1818
"affected_version_range": "vers:gem/<=1.3.1",
19-
"fixed_version": null
19+
"fixed_version": "1.3.2"
2020
}
2121
],
2222
"references": [
@@ -85,8 +85,8 @@
8585
},
8686
{
8787
"aliases": [
88-
"CVE-2022-21831",
89-
"GHSA-w749-p3v6-hccq"
88+
"GHSA-w749-p3v6-hccq",
89+
"CVE-2022-21831"
9090
],
9191
"summary": "Possible code injection vulnerability in Rails / Active Storage",
9292
"affected_packages": [
@@ -139,8 +139,8 @@
139139
},
140140
{
141141
"aliases": [
142-
"CVE-2022-21831",
143-
"GHSA-w749-p3v6-hccq"
142+
"GHSA-w749-p3v6-hccq",
143+
"CVE-2022-21831"
144144
],
145145
"summary": "Possible code injection vulnerability in Rails / Active Storage",
146146
"affected_packages": [
@@ -193,8 +193,8 @@
193193
},
194194
{
195195
"aliases": [
196-
"CVE-2022-21831",
197-
"GHSA-w749-p3v6-hccq"
196+
"GHSA-w749-p3v6-hccq",
197+
"CVE-2022-21831"
198198
],
199199
"summary": "Possible code injection vulnerability in Rails / Active Storage",
200200
"affected_packages": [
@@ -247,8 +247,8 @@
247247
},
248248
{
249249
"aliases": [
250-
"CVE-2022-21831",
251-
"GHSA-w749-p3v6-hccq"
250+
"GHSA-w749-p3v6-hccq",
251+
"CVE-2022-21831"
252252
],
253253
"summary": "Possible code injection vulnerability in Rails / Active Storage",
254254
"affected_packages": [

vulnerabilities/tests/test_data/github_api/gem.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
"package": {
5858
"name": "webrick"
5959
},
60+
"firstPatchedVersion": {
61+
"identifier" :"1.3.2"
62+
},
6063
"vulnerableVersionRange": "<= 1.3.1"
6164
}
6265
},

vulnerabilities/tests/test_data/github_api/golang-expected.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[
22
{
33
"aliases": [
4-
"CVE-2014-9356",
5-
"GHSA-vj3f-3286-r4pf"
4+
"GHSA-vj3f-3286-r4pf",
5+
"CVE-2014-9356"
66
],
77
"summary": "Path Traversal in Docker",
88
"affected_packages": [
@@ -16,7 +16,7 @@
1616
"subpath": null
1717
},
1818
"affected_version_range": "vers:golang/<1.3.3",
19-
"fixed_version": null
19+
"fixed_version": "1.3.3"
2020
}
2121
],
2222
"references": [
@@ -65,8 +65,8 @@
6565
},
6666
{
6767
"aliases": [
68-
"CVE-2014-9356",
69-
"GHSA-vj3f-3286-r4pf"
68+
"GHSA-vj3f-3286-r4pf",
69+
"CVE-2014-9356"
7070
],
7171
"summary": "Path Traversal in Docker",
7272
"affected_packages": [
@@ -129,8 +129,8 @@
129129
},
130130
{
131131
"aliases": [
132-
"CVE-2021-39183",
133-
"GHSA-2hfj-cxw7-g45p"
132+
"GHSA-2hfj-cxw7-g45p",
133+
"CVE-2021-39183"
134134
],
135135
"summary": "Unsafe inline XSS in pasting DOM element into chat",
136136
"affected_packages": [

vulnerabilities/tests/test_data/github_api/golang.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
"package": {
4646
"name": "github.com/moby/moby"
4747
},
48+
"firstPatchedVersion": {
49+
"identifier" :"1.3.3"
50+
},
4851
"vulnerableVersionRange": "< 1.3.3"
4952
}
5053
},

vulnerabilities/tests/test_data/github_api/maven-expected.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[
22
{
33
"aliases": [
4-
"CVE-2019-0199",
5-
"GHSA-qcxh-w3j9-58qr"
4+
"GHSA-qcxh-w3j9-58qr",
5+
"CVE-2019-0199"
66
],
77
"summary": "Denial of Service in Tomcat",
88
"affected_packages": [
@@ -35,8 +35,8 @@
3535
},
3636
{
3737
"aliases": [
38-
"CVE-2019-0199",
39-
"GHSA-qcxh-w3j9-58qr"
38+
"GHSA-qcxh-w3j9-58qr",
39+
"CVE-2019-0199"
4040
],
4141
"summary": "Denial of Service in Tomcat",
4242
"affected_packages": [
@@ -69,8 +69,8 @@
6969
},
7070
{
7171
"aliases": [
72-
"CVE-2020-1938",
73-
"GHSA-c9hw-wf7x-jp9j"
72+
"GHSA-c9hw-wf7x-jp9j",
73+
"CVE-2020-1938"
7474
],
7575
"summary": "Improper Input Validation in Tomcat",
7676
"affected_packages": [
@@ -103,8 +103,8 @@
103103
},
104104
{
105105
"aliases": [
106-
"CVE-2020-1938",
107-
"GHSA-c9hw-wf7x-jp9j"
106+
"GHSA-c9hw-wf7x-jp9j",
107+
"CVE-2020-1938"
108108
],
109109
"summary": "Improper Input Validation in Tomcat",
110110
"affected_packages": [
@@ -137,8 +137,8 @@
137137
},
138138
{
139139
"aliases": [
140-
"CVE-2020-1938",
141-
"GHSA-c9hw-wf7x-jp9j"
140+
"GHSA-c9hw-wf7x-jp9j",
141+
"CVE-2020-1938"
142142
],
143143
"summary": "Improper Input Validation in Tomcat",
144144
"affected_packages": [
@@ -152,7 +152,7 @@
152152
"subpath": null
153153
},
154154
"affected_version_range": "vers:maven/>=9.0.0|<9.0.31",
155-
"fixed_version": null
155+
"fixed_version": "9.0.1"
156156
}
157157
],
158158
"references": [

0 commit comments

Comments
 (0)