Skip to content

Commit ebaee7d

Browse files
committed
Avoid mixing explicit affected packages with last known affected ranges to keep ranges consistent.
Signed-off-by: ziad hany <[email protected]>
1 parent 29003da commit ebaee7d

File tree

14 files changed

+697
-82
lines changed

14 files changed

+697
-82
lines changed

vulnerabilities/importers/osv_v2.py

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
from cvss.exceptions import CVSS3MalformedError
1818
from cvss.exceptions import CVSS4MalformedError
1919
from packageurl import PackageURL
20+
from univers.version_constraint import InvalidConstraintsError
2021
from univers.version_constraint import VersionConstraint
21-
from univers.version_constraint import simplify_constraints
22+
from univers.version_constraint import validate_comparators
2223
from univers.version_range import RANGE_CLASS_BY_SCHEMES
24+
from univers.version_range import build_range_from_github_advisory_constraint
2325
from univers.versions import InvalidVersion
2426
from univers.versions import SemverVersion
2527

@@ -83,20 +85,6 @@ def parse_advisory_data_v3(
8385
continue
8486

8587
affected_constraints = []
86-
explicit_affected_constraints = get_explicit_affected_constraints(
87-
affected_pkg=affected_pkg,
88-
raw_id=advisory_id,
89-
supported_ecosystem=purl.type,
90-
)
91-
affected_constraints.extend(explicit_affected_constraints)
92-
93-
last_known_affected = get_last_known_affected__constraint(
94-
affected_pkg=affected_pkg,
95-
raw_id=advisory_id,
96-
supported_ecosystem=purl.type,
97-
)
98-
affected_constraints.extend(last_known_affected)
99-
10088
fixed_constraints = []
10189
for r in affected_pkg.get("ranges") or []:
10290
(
@@ -109,9 +97,11 @@ def parse_advisory_data_v3(
10997
raw_id=advisory_id,
11098
supported_ecosystem=purl.type,
11199
)
100+
if affected_constraint:
101+
affected_constraints.extend(affected_constraint)
112102

113-
affected_constraints.extend(affected_constraint)
114-
fixed_constraints.extend(fixed_constraint)
103+
if fixed_constraint:
104+
fixed_constraints.extend(fixed_constraint)
115105

116106
repo_url = r.get("repo")
117107
commit_processing_queue = [
@@ -139,22 +129,27 @@ def parse_advisory_data_v3(
139129
references.append(patch_obj)
140130

141131
version_range_class = RANGE_CLASS_BY_SCHEMES.get(purl.type)
142-
143132
affected_version_range = None
144133
if affected_constraints:
145134
try:
146-
affected_version_range = version_range_class(
147-
constraints=simplify_constraints(affected_constraints)
148-
)
135+
valid_affected_constraints = VersionConstraint.simplify(affected_constraints)
136+
if not validate_comparators(valid_affected_constraints):
137+
raise InvalidConstraintsError(
138+
f"Failed to build Affected VersionRange Constraints for {advisory_id}: {valid_affected_constraints}"
139+
)
140+
affected_version_range = version_range_class(constraints=valid_affected_constraints)
149141
except Exception as e:
150142
logger.error(f"Failed to build VersionRange for {advisory_id}: {e}")
151143

152144
fixed_version_range = None
153145
if fixed_constraints:
154146
try:
155-
fixed_version_range = version_range_class(
156-
constraints=simplify_constraints(fixed_constraints)
157-
)
147+
valid_fixed_constraints = VersionConstraint.simplify(fixed_constraints)
148+
if not validate_comparators(valid_fixed_constraints):
149+
raise InvalidConstraintsError(
150+
f"Failed to build Fixed VersionRange Constraints for {advisory_id}: {valid_fixed_constraints}"
151+
)
152+
fixed_version_range = version_range_class(constraints=valid_fixed_constraints)
158153
except Exception as e:
159154
logger.error(f"Failed to build VersionRange for {advisory_id}: {e}")
160155

@@ -177,6 +172,32 @@ def parse_advisory_data_v3(
177172
except Exception as e:
178173
logger.error(f"Invalid AffectedPackageV2 {e} for {advisory_id}")
179174

175+
explicit_affected_range = get_explicit_affected_range(
176+
affected_pkg=affected_pkg,
177+
raw_id=advisory_id,
178+
supported_ecosystem=purl.type,
179+
)
180+
if explicit_affected_range:
181+
affected_packages.append(
182+
AffectedPackageV2(
183+
package=purl,
184+
affected_version_range=explicit_affected_range,
185+
)
186+
)
187+
188+
explicit_last_known_affected_range = get_last_known_affected_range(
189+
affected_pkg=affected_pkg,
190+
raw_id=advisory_id,
191+
supported_ecosystem=purl.type,
192+
)
193+
if explicit_last_known_affected_range:
194+
affected_packages.append(
195+
AffectedPackageV2(
196+
package=purl,
197+
affected_version_range=explicit_last_known_affected_range,
198+
)
199+
)
200+
180201
database_specific = raw_data.get("database_specific") or {}
181202
cwe_ids = database_specific.get("cwe_ids") or []
182203
weaknesses = list(map(get_cwe_id, cwe_ids))
@@ -335,17 +356,17 @@ def get_affected_purl(affected_pkg, raw_id):
335356
return None
336357

337358

338-
def get_explicit_affected_constraints(affected_pkg, raw_id, supported_ecosystem):
359+
def get_explicit_affected_range(affected_pkg, raw_id, supported_ecosystem):
339360
"""
340-
Return a list of explicit version constraints for the ``affected_pkg`` data.
361+
Return an explicit affected version range for the affected package data.
341362
"""
342363
affected_versions = affected_pkg.get("versions") or []
343364
constraints = []
344365

345366
version_range_class = RANGE_CLASS_BY_SCHEMES.get(supported_ecosystem)
346367
if not version_range_class:
347368
logger.error(f"unsupported ecosystem {supported_ecosystem}")
348-
return []
369+
return
349370

350371
for version in affected_versions:
351372
try:
@@ -356,30 +377,33 @@ def get_explicit_affected_constraints(affected_pkg, raw_id, supported_ecosystem)
356377
logger.error(
357378
f"Invalid VersionConstraint: {version} " f"for OSV id: {raw_id!r}: error:{e!r}"
358379
)
359-
return constraints
380+
if not constraints:
381+
return
382+
return version_range_class(constraints=constraints)
360383

361384

362-
def get_last_known_affected__constraint(affected_pkg, raw_id, supported_ecosystem):
385+
def get_last_known_affected_range(affected_pkg, raw_id, supported_ecosystem):
363386
"""
364387
Return the last_known_affected_version_range from the database_specific
365388
"""
366389
database_specific = affected_pkg.get("database_specific") or {}
367390
last_known_value = database_specific.get("last_known_affected_version_range")
368391

369392
if not last_known_value:
370-
return []
393+
return
371394

372395
try:
373-
version_range_class = RANGE_CLASS_BY_SCHEMES.get(supported_ecosystem)
374-
version_range = version_range_class.from_native(last_known_value)
375-
return version_range.constraints
396+
affected_version_range = build_range_from_github_advisory_constraint(
397+
supported_ecosystem, last_known_value
398+
)
399+
return affected_version_range
376400

377401
except Exception as e:
378402
logger.error(
379403
f"Invalid VersionConstraint in last_known_affected_version_range: {last_known_value!r} "
380404
f"for OSV id: {raw_id!r}: error:{e!r}"
381405
)
382-
return []
406+
return
383407

384408

385409
def get_version_ranges_constraints(ranges, raw_id, supported_ecosystem):
@@ -419,7 +443,7 @@ def get_version_ranges_constraints(ranges, raw_id, supported_ecosystem):
419443
for event_type, event_value in extract_events(ranges):
420444
if range_type == "GIT":
421445
if event_value == "0":
422-
event_value = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
446+
continue
423447

424448
if event_type == "fixed":
425449
fixed_commits.append(event_value)

vulnerabilities/pipelines/v2_importers/github_osv_importer.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from pathlib import Path
1212
from typing import Iterable
1313

14-
from fetchcode.vcs import fetch_via_vcs
14+
from fetchcode.vcs import fetch_via_vcs, VCSResponse
1515

1616
from vulnerabilities.importer import AdvisoryData
1717
from vulnerabilities.importers.osv_v2 import parse_advisory_data_v3
@@ -41,7 +41,8 @@ def steps(cls):
4141

4242
def clone(self):
4343
self.log(f"Cloning `{self.repo_url}`")
44-
self.vcs_response = fetch_via_vcs(self.repo_url)
44+
# self.vcs_response = fetch_via_vcs(self.repo_url)
45+
self.vcs_response = VCSResponse(dest_dir="/home/ziad-hany/PycharmProjects/advisory-database", vcs_type="git", domain="GitHub")
4546

4647
def advisories_count(self):
4748
advisory_dir = Path(self.vcs_response.dest_dir) / "advisories/github-reviewed"
@@ -79,9 +80,10 @@ def collect_advisories(self) -> Iterable[AdvisoryData]:
7980
)
8081

8182
def clean_downloads(self):
82-
if self.vcs_response:
83-
self.log("Removing cloned repository")
84-
self.vcs_response.delete()
83+
pass
84+
# if self.vcs_response:
85+
# self.log("Removing cloned repository")
86+
# self.vcs_response.delete()
8587

8688
def on_failure(self):
8789
self.clean_downloads()
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-8hxh-r6f7-jf45",
4+
"modified": "2021-10-04T21:26:20Z",
5+
"published": "2020-10-16T17:03:43Z",
6+
"aliases": [],
7+
"summary": "Memory exhaustion in http4s-async-http-client with large or malicious compressed responses",
8+
"details": "### Impact\nA server we connect to with http4s-async-http-client could theoretically respond with a large or malicious compressed stream and exhaust memory in the client JVM. It does not affect http4s servers, other client backends, or clients that speak only to trusted servers. This is related to a transitive dependency on netty-codec-4.1.45.Final, which is affected by [CVE-2020-11612](https://app.snyk.io/vuln/SNYK-JAVA-IONETTY-564897).\n\n### Patches\nUpgrade to http4s-async-http-client >= 0.21.8. All 1.0 milestones are also safe.\n\n### Workarounds\nAdd an explicit runtime dependency on async-http-client's netty dependencies that evicts them to an unaffected version:\n\n```scala\nlibraryDependencies ++= Seq(\n \"io.netty\" % \"netty-codec\" % \"4.1.53.Final\" % Runtime,\n \"io.netty\" % \"netty-codec-socks\" % \"4.1.53.Final\" % Runtime,\n \"io.netty\" % \"netty-handler-proxy\" % \"4.1.53.Final\" % Runtime,\n \"io.netty\" % \"netty-common\" % \"4.1.53.Final\" % Runtime,\n \"io.netty\" % \"netty-transport\" % \"4.1.53.Final\" % Runtime,\n \"io.netty\" % \"netty-handler\" % \"4.1.53.Final\" % Runtime,\n \"io.netty\" % \"netty-resolver-dns\" % \"4.1.53.Final\" % Runtime\n)\n```\n\n### References\n* https://app.snyk.io/vuln/SNYK-JAVA-IONETTY-564897\n* https://github.com/http4s/http4s/issues/3681\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [http4s](https://github.com/http4s/http4s/issues/new)\n* Contact a maintainer privately per [http4s' security policy](https://github.com/http4s/http4s/blob/master/SECURITY.md#reporting-a-vulnerability)",
9+
"severity": [],
10+
"affected": [
11+
{
12+
"package": {
13+
"ecosystem": "Maven",
14+
"name": "org.http4s:http4s-async-http-client_2.13"
15+
},
16+
"ranges": [
17+
{
18+
"type": "ECOSYSTEM",
19+
"events": [
20+
{
21+
"introduced": "0"
22+
},
23+
{
24+
"fixed": "0.21.8"
25+
}
26+
]
27+
}
28+
],
29+
"database_specific": {
30+
"last_known_affected_version_range": "<= 0.21.7"
31+
}
32+
},
33+
{
34+
"package": {
35+
"ecosystem": "Maven",
36+
"name": "org.http4s:http4s-async-http-client_2.12"
37+
},
38+
"ranges": [
39+
{
40+
"type": "ECOSYSTEM",
41+
"events": [
42+
{
43+
"introduced": "0"
44+
},
45+
{
46+
"fixed": "0.21.8"
47+
}
48+
]
49+
}
50+
],
51+
"database_specific": {
52+
"last_known_affected_version_range": "<= 0.21.7"
53+
}
54+
}
55+
],
56+
"references": [
57+
{
58+
"type": "WEB",
59+
"url": "https://github.com/http4s/http4s/security/advisories/GHSA-8hxh-r6f7-jf45"
60+
},
61+
{
62+
"type": "PACKAGE",
63+
"url": "https://github.com/http4s/http4s"
64+
}
65+
],
66+
"database_specific": {
67+
"cwe_ids": [
68+
"CWE-400"
69+
],
70+
"severity": "LOW",
71+
"github_reviewed": true,
72+
"github_reviewed_at": "2020-10-16T17:03:18Z",
73+
"nvd_published_at": null
74+
}
75+
}

vulnerabilities/tests/test_data/osv_test/github/github-expected-2.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@
1818
"fixed_version_range": "vers:composer/2.9.5",
1919
"introduced_by_commit_patches": [],
2020
"fixed_by_commit_patches": []
21+
},
22+
{
23+
"package": {
24+
"type": "composer",
25+
"namespace": "devcode-it",
26+
"name": "openstamanager",
27+
"version": "",
28+
"qualifiers": "",
29+
"subpath": ""
30+
},
31+
"affected_version_range": "vers:composer/<=2.9.4",
32+
"fixed_version_range": null,
33+
"introduced_by_commit_patches": [],
34+
"fixed_by_commit_patches": []
2135
}
2236
],
2337
"references_v2": [

0 commit comments

Comments
 (0)