Skip to content

Commit 8d5ca76

Browse files
committed
Update parse_advisory() and tests #597
Reference: #597 Signed-off-by: John M. Horan <[email protected]>
1 parent 664af89 commit 8d5ca76

File tree

2 files changed

+41
-67
lines changed

2 files changed

+41
-67
lines changed

vulnerabilities/importers/archlinux.py

Lines changed: 38 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66
# See https://github.com/nexB/vulnerablecode for support or download.
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
9-
import dataclasses
10-
import json
11-
import pprint
9+
1210
from typing import Iterable
1311
from typing import List
1412
from typing import Mapping
15-
from typing import Set
1613
from urllib.request import urlopen
1714

1815
from packageurl import PackageURL
@@ -22,34 +19,11 @@
2219
from vulnerabilities.importer import Importer
2320
from vulnerabilities.importer import Reference
2421
from vulnerabilities.importer import VulnerabilitySeverity
25-
26-
# 9/28/2022 Wednesday 12:58:46 PM. Do we need the next import? It's used at the bottom!
27-
from vulnerabilities.models import Advisory
28-
29-
# 9/28/2022 Wednesday 1:04:27 PM. From /home/jmh/dev/nexb/vulnerablecode/vulnerabilities/importers/alpine_linux.py
30-
# copy fetch_response function to vulnerabilities.utils then import here and use below
3122
from vulnerabilities.utils import fetch_response
3223
from vulnerabilities.utils import nearest_patched_package
3324

34-
# Take a URL -> Grab the data from the URL -> Map it according to AdvisoryData
35-
3625

3726
class ArchlinuxImporter(Importer):
38-
# def __enter__(self):
39-
# self._api_response = self._fetch()
40-
41-
# def updated_advisories(self) -> Set[AdvisoryData]:
42-
# advisories = []
43-
44-
# for record in self._api_response:
45-
# advisories.extend(self._parse(record))
46-
47-
# return self.batch_advisories(advisories)
48-
49-
# def _fetch(self) -> Iterable[Mapping]:
50-
# with urlopen(self.config.archlinux_tracker_url) as response:
51-
# return json.load(response)
52-
5327
url = "https://security.archlinux.org/json"
5428
spdx_license_expression = "unknown"
5529

@@ -61,20 +35,21 @@ def advisory_data(self) -> Iterable[AdvisoryData]:
6135
for record in self.fetch():
6236
yield self.parse_advisory(record)
6337

64-
# def _parse(self, record) -> List[AdvisoryData]:
38+
# The JSON includes 'status' and 'type' fields do we want to incorporate them into the AdvisoryData objects?
39+
# Although not directly reflected in the JSON, the web page for at least some references include an additional reference,
40+
# see, e.g., https://security.archlinux.org/AVG-2781 (one of our test inputs, which lists this ref: https://github.com/jpadilla/pyjwt/security/advisories/GHSA-ffqj-6fqr-9h24)
41+
# Do we want to incorporate them into the AdvisoryData objects?
6542
def parse_advisory(self, record) -> List[AdvisoryData]:
6643
advisories = []
6744
aliases = record["issues"]
68-
for cve_id in record["issues"]:
45+
for alias in record["issues"]:
6946
affected_packages = []
7047
for name in record["packages"]:
7148
impacted_purls, resolved_purls = [], []
7249
impacted_purls.append(
7350
PackageURL(
7451
name=name,
75-
# type="pacman",
76-
# type="alpm",
77-
type="archlinux",
52+
type="alpm",
7853
namespace="archlinux",
7954
version=record["affected"],
8055
)
@@ -84,9 +59,7 @@ def parse_advisory(self, record) -> List[AdvisoryData]:
8459
resolved_purls.append(
8560
PackageURL(
8661
name=name,
87-
# type="pacman",
88-
# type="alpm",
89-
type="archlinux",
62+
type="alpm",
9063
namespace="archlinux",
9164
version=record["fixed"],
9265
)
@@ -115,26 +88,41 @@ def parse_advisory(self, record) -> List[AdvisoryData]:
11588
)
11689

11790
advisories.append(
118-
# Advisory(
11991
AdvisoryData(
120-
# deprecated
121-
# vulnerability_id=cve_id,
122-
aliases=[cve_id],
123-
# summary="",
92+
# Do we want/need to keep this inside a list? "aliases" is plural but I understand we want to break out each alias individually.
93+
# However, it looks like alpine_linux.py and nginx.py, for example, return a list of aliases.
94+
aliases=[alias],
95+
# aliases=alias,
96+
summary="",
12497
affected_packages=affected_packages,
12598
references=references,
12699
)
127100
)
128101

129-
print("\rHello World!\r")
130-
131-
print("\radvisories = {}\r".format(advisories))
132-
133-
for apple in advisories:
134-
# pprint.pprint(apple.to_dict())
135-
print(apple.affected_packages)
136-
print(f"aliases: {apple.aliases}")
137-
print(f"summary: {apple.summary}")
138-
print(f"affected_packages: {apple.affected_packages}")
102+
# The print statements below will print the structure of each test advisory when either of these tests is run:
103+
# pytest -vvs -k test_parse_advisory_single vulnerabilities/tests/test_archlinux.py
104+
# pytest -vvs -k test_parse_advisory_multi vulnerabilities/tests/test_archlinux.py
105+
106+
print("\n\r=================================\n\r")
107+
108+
for advisory in advisories:
109+
print(f"1. aliases: {advisory.aliases}\r")
110+
print("")
111+
print(f"2. summary: {advisory.summary}\r")
112+
print("")
113+
print(f"3. affected_packages: {advisory.affected_packages}\r")
114+
for pkg in advisory.affected_packages:
115+
print("")
116+
print("vulnerable_package: {}\r".format(pkg.vulnerable_package))
117+
print("")
118+
print("patched_package: {}\r".format(pkg.patched_package))
119+
print("")
120+
print(f"4. references: {advisory.references}\r")
121+
for ref in advisory.references:
122+
print("")
123+
print("ref: {}\r".format(ref))
124+
print("")
125+
print(f"5. date_published: {advisory.date_published}\r")
126+
print("\n\r=================================\n\r")
139127

140128
return advisories

vulnerabilities/tests/test_archlinux.py

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,7 @@ def assert_for_package(self, name, version, cve_ids=None):
103103
assert cve_ids == {v.vulnerability_id for v in qs[0].vulnerabilities.all()}
104104

105105

106-
# 9/28/2022 Wednesday 12:45:59 PM. https://security.archlinux.org/json -- view in Firefox, copy, paste, change null to None
107-
def test_parse_advisory():
106+
def test_parse_advisory_single():
108107
record = {
109108
"name": "AVG-2781",
110109
"packages": ["python-pyjwt"],
@@ -121,21 +120,7 @@ def test_parse_advisory():
121120
assert archlinux.ArchlinuxImporter().parse_advisory(record)
122121

123122

124-
# 9/29/2022 Thursday 9:08:38 PM.
125123
def test_parse_advisory_multi():
126-
# record = {
127-
# "name": "AVG-2781",
128-
# "packages": ["python-pyjwt"],
129-
# "status": "Unknown",
130-
# "severity": "Unknown",
131-
# "type": "unknown",
132-
# "affected": "2.3.0-1",
133-
# "fixed": "2.4.0-1",
134-
# "ticket": None,
135-
# "issues": ["CVE-2022-29217"],
136-
# "advisories": [],
137-
# }
138-
139124
record_list = [
140125
{
141126
"name": "AVG-2781",
@@ -175,4 +160,5 @@ def test_parse_advisory_multi():
175160
},
176161
]
177162

178-
assert archlinux.ArchlinuxImporter().parse_advisory(record_list)
163+
for record in record_list:
164+
assert archlinux.ArchlinuxImporter().parse_advisory(record)

0 commit comments

Comments
 (0)