Skip to content

Commit 368a9ec

Browse files
committed
Refactor the code for npm_live importer
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
1 parent 0dfd93e commit 368a9ec

4 files changed

Lines changed: 98 additions & 33 deletions

File tree

vulnerabilities/pipelines/v2_importers/npm_live_importer.py

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
from typing import Iterable
1212

1313
from packageurl import PackageURL
14+
from univers.versions import InvalidVersion
1415
from univers.versions import SemverVersion
1516

16-
from vulnerabilities.importer import AdvisoryData
17+
from vulnerabilities.importer import AdvisoryDataV2
1718
from vulnerabilities.pipelines.v2_importers.npm_importer import NpmImporterPipeline
1819
from vulnerabilities.utils import load_json
1920

@@ -58,31 +59,35 @@ def get_purl_inputs(self):
5859

5960
self.purl = purl
6061

61-
def collect_advisories(self) -> Iterable[AdvisoryData]:
62+
def collect_advisories(self) -> Iterable[AdvisoryDataV2]:
6263
vuln_directory = Path(self.vcs_response.dest_dir) / "vuln" / "npm"
63-
advisory_files = list(vuln_directory.glob("*.json"))
64-
6564
package_name = self.purl.name
6665
filtered_files = []
67-
for advisory_file in advisory_files:
68-
try:
69-
data = load_json(advisory_file)
70-
if data.get("module_name") == package_name:
71-
affected_package = self.get_affected_package(data, package_name)
72-
if not self.purl.version or self._version_is_affected(affected_package):
73-
filtered_files.append(advisory_file)
74-
except Exception as e:
75-
self.log(f"Error processing advisory file {advisory_file}: {str(e)}")
76-
advisory_files = filtered_files
77-
78-
for advisory in list(advisory_files):
66+
for advisory_file in vuln_directory.glob("*.json"):
67+
data = load_json(advisory_file)
68+
if data.get("module_name") == package_name:
69+
affected_package = self.get_affected_package(data, package_name)
70+
if not self.purl.version or self._version_is_related(affected_package):
71+
filtered_files.append(advisory_file)
72+
73+
for advisory in filtered_files:
7974
result = self.to_advisory_data(advisory)
8075
if result:
8176
yield result
8277

83-
def _version_is_affected(self, affected_package):
84-
if not self.purl.version or not affected_package.affected_version_range:
78+
def _version_is_related(self, affected_package):
79+
try:
80+
package_version = SemverVersion(self.purl.version)
81+
except InvalidVersion as e:
82+
self.log(f"Invalid PURL version: {self.purl.version!r}: {str(e)}")
83+
return False
84+
85+
if (
86+
affected_package.affected_version_range
87+
and package_version in affected_package.affected_version_range
88+
) or (
89+
affected_package.fixed_version_range
90+
and package_version in affected_package.fixed_version_range
91+
):
8592
return True
86-
87-
purl_version = SemverVersion(self.purl.version)
88-
return purl_version in affected_package.affected_version_range
93+
return False

vulnerabilities/tests/pipelines/v2_importers/test_npm_live_importer_pipeline_v2.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020

2121
from vulnerabilities.importer import AffectedPackageV2
2222
from vulnerabilities.pipelines.v2_importers.npm_live_importer import NpmLiveImporterPipeline
23+
from vulnerabilities.tests import util_tests
2324

24-
TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "npm"
25+
TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "npm_live"
2526

2627

2728
def test_package_first_mode_valid_npm_package(tmp_path):
@@ -37,17 +38,15 @@ def test_package_first_mode_valid_npm_package(tmp_path):
3738

3839
mock_vcs_response = SimpleNamespace(dest_dir=str(tmp_path), delete=lambda: None)
3940

40-
purl = PackageURL(type="npm", name="npm", version="1.2.0")
41+
purl = PackageURL(type="npm", name="decamelize", version="1.1.0")
4142
pipeline = NpmLiveImporterPipeline(purl=purl)
4243
pipeline.vcs_response = mock_vcs_response
4344

4445
pipeline.get_purl_inputs()
45-
advisories = list(pipeline.collect_advisories())
4646

47-
assert len(advisories) == 1
48-
assert advisories[0].aliases == ["CVE-2013-4116"]
49-
assert len(advisories[0].affected_packages) == 1
50-
assert advisories[0].affected_packages[0].package.name == "npm"
47+
result = [adv.to_dict() for adv in pipeline.collect_advisories()]
48+
expected_file = Path(TEST_DATA / "parse-advisory-npm-expected.json")
49+
util_tests.check_results_against_json(result, expected_file)
5150

5251

5352
def test_package_first_mode_unaffected_version(tmp_path):
@@ -124,10 +123,7 @@ def test_version_is_affected():
124123
),
125124
)
126125

127-
assert pipeline._version_is_affected(affected_package) == True
126+
assert pipeline._version_is_related(affected_package) == True
128127

129128
pipeline.purl = PackageURL(type="npm", name="npm", version="1.4.0")
130-
assert pipeline._version_is_affected(affected_package) == False
131-
132-
pipeline.purl = PackageURL(type="npm", name="npm")
133-
assert pipeline._version_is_affected(affected_package) == True
129+
assert pipeline._version_is_related(affected_package) == False
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"id": 308,
3+
"created_at": "2017-01-26",
4+
"updated_at": "2017-04-14",
5+
"title": "Regular Expression Denial of Service",
6+
"author": {
7+
"name": "saurik",
8+
"website": null,
9+
"username": null
10+
},
11+
"module_name": "decamelize",
12+
"publish_date": "2017-04-14",
13+
"cves": [],
14+
"vulnerable_versions": ">=1.1.0 <=1.1.1",
15+
"patched_versions": ">=1.1.2",
16+
"overview": "Decamelize is used to convert a dash/dot/underscore/space separated string to camelCase. \n\nDecamelize uses regular expressions to evaluate a string and takes unescaped separator values, which can be used to create a denial of service attack.",
17+
"recommendation": "Upgrade to version 1.1.2 or later.",
18+
"references": [
19+
"https://github.com/sindresorhus/decamelize/issues/5"
20+
],
21+
"cvss_vector": null,
22+
"cvss_score": null,
23+
"coordinating_vendor": "^Lift Security"
24+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[
2+
{
3+
"advisory_id": "npm-308",
4+
"aliases": [],
5+
"summary": "Regular Expression Denial of Service\nDecamelize is used to convert a dash/dot/underscore/space separated string to camelCase. \n\nDecamelize uses regular expressions to evaluate a string and takes unescaped separator values, which can be used to create a denial of service attack.",
6+
"affected_packages": [
7+
{
8+
"package": {
9+
"type": "npm",
10+
"namespace": "",
11+
"name": "decamelize",
12+
"version": "",
13+
"qualifiers": "",
14+
"subpath": ""
15+
},
16+
"affected_version_range": "vers:npm/>=1.1.0|<=1.1.1",
17+
"fixed_version_range": "vers:npm/>=1.1.2",
18+
"introduced_by_commit_patches": [],
19+
"fixed_by_commit_patches": []
20+
}
21+
],
22+
"references": [
23+
{
24+
"reference_id": "",
25+
"reference_type": "",
26+
"url": "https://github.com/sindresorhus/decamelize/issues/5"
27+
},
28+
{
29+
"reference_id": "308",
30+
"reference_type": "",
31+
"url": "https://github.com/nodejs/security-wg/blob/main/vuln/npm/308.json"
32+
}
33+
],
34+
"patches": [],
35+
"severities": [],
36+
"date_published": "2017-01-26T00:00:00+00:00",
37+
"weaknesses": [],
38+
"url": "https://github.com/nodejs/security-wg/blob/main/vuln/npm/308.json"
39+
}
40+
]

0 commit comments

Comments
 (0)