Skip to content

Commit 1f2be03

Browse files
committed
refactor: replace classmethod w/ func and more
Refactors based on requested review #393 (review) Signed-off-by: Hritik Vijay <hritikxx8@gmail.com>
1 parent 31de219 commit 1f2be03

File tree

1 file changed

+125
-108
lines changed

1 file changed

+125
-108
lines changed

vulnerabilities/importers/mozilla.py

Lines changed: 125 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from vulnerabilities.helpers import split_markdown_front_matter
1616
from vulnerabilities.severity_systems import scoring_systems
1717

18-
1918
REPOSITORY = "mozilla/foundation-security-advisories"
2019
MFSA_FILENAME_RE = re.compile(r"mfsa(\d{4}-\d{2,3})\.(md|yml)$")
2120

@@ -37,128 +36,146 @@ def updated_advisories(self) -> Set[Advisory]:
3736

3837
advisories = []
3938
for path in files:
40-
advisories.extend(self.to_advisories(path))
39+
advisories.extend(to_advisories(path))
4140

4241
return self.batch_advisories(advisories)
4342

44-
def to_advisories(self, path: str) -> List[Advisory]:
45-
"""
46-
Convert a file to corresponding advisories.
47-
This calls proper method to handle yml/md files.
48-
"""
49-
mfsa_id = self.mfsa_id_from_filename(path)
50-
51-
with open(path) as lines:
52-
if path.endswith(".md"):
53-
return self.get_advisories_from_md(mfsa_id, lines)
54-
if path.endswith(".yml"):
55-
return self.get_advisories_from_yml(mfsa_id, lines)
5643

44+
def to_advisories(path: str) -> List[Advisory]:
45+
"""
46+
Convert a file to corresponding advisories.
47+
This calls proper method to handle yml/md files.
48+
"""
49+
mfsa_id = mfsa_id_from_filename(path)
50+
if not mfsa_id:
5751
return []
5852

59-
def get_advisories_from_yml(self, mfsa_id, lines) -> List[Advisory]:
60-
advisories = []
61-
data = yaml.safe_load(lines)
62-
data["mfsa_id"] = mfsa_id
63-
64-
fixed_package_urls = self.get_package_urls(data.get("fixed_in"))
65-
references = self.get_yml_references(data)
66-
67-
if not data.get("advisories"):
68-
return []
69-
70-
for cve, advisory in data["advisories"].items():
71-
advisories.append(
72-
Advisory(
73-
summary=advisory.get("description"),
74-
vulnerability_id=cve if is_cve(cve) else "",
75-
impacted_package_urls=[],
76-
resolved_package_urls=fixed_package_urls,
77-
references=references,
78-
)
79-
)
53+
with open(path) as lines:
54+
if path.endswith(".md"):
55+
return get_advisories_from_md(mfsa_id, lines)
56+
if path.endswith(".yml"):
57+
return get_advisories_from_yml(mfsa_id, lines)
8058

81-
return advisories
82-
83-
def get_advisories_from_md(self, mfsa_id, lines) -> List[Advisory]:
84-
yamltext, mdtext = split_markdown_front_matter(lines.read())
85-
data = yaml.safe_load(yamltext)
86-
data["mfsa_id"] = mfsa_id
87-
88-
fixed_package_urls = self.get_package_urls(data.get("fixed_in"))
89-
references = self.get_yml_references(data)
90-
cves = re.findall(r"CVE-\d+-\d+", yamltext + mdtext, re.IGNORECASE)
91-
for cve in cves:
92-
references.append(
93-
Reference(
94-
reference_id=cve, url=f"https://cve.mitre.org/cgi-bin/cvename.cgi?name={cve}"
95-
)
96-
)
59+
return []
60+
61+
62+
def get_advisories_from_yml(mfsa_id, lines) -> List[Advisory]:
63+
advisories = []
64+
data = yaml.safe_load(lines)
65+
data["mfsa_id"] = mfsa_id
9766

98-
description = self.html_get_p_under_h3(markdown(mdtext), "description")
67+
fixed_package_urls = get_package_urls(data.get("fixed_in"))
68+
references = get_yml_references(data)
9969

100-
return [
70+
if not data.get("advisories"):
71+
return []
72+
73+
for cve, advisory in data["advisories"].items():
74+
# These may contain HTML tags
75+
summary = BeautifulSoup(advisory.get("description", ""), features="lxml").get_text()
76+
77+
advisories.append(
10178
Advisory(
102-
summary=description,
103-
vulnerability_id="",
79+
summary=summary,
80+
vulnerability_id=cve if is_cve(cve) else "",
10481
impacted_package_urls=[],
10582
resolved_package_urls=fixed_package_urls,
10683
references=references,
10784
)
108-
]
109-
110-
def html_get_p_under_h3(self, html, h3: str):
111-
soup = BeautifulSoup(html, features="lxml")
112-
h3tag = soup.find("h3", text=lambda txt: txt.lower() == h3)
113-
p = ""
114-
if h3tag:
115-
for tag in h3tag.next_siblings:
116-
if tag.name:
117-
if tag.name != "p":
118-
break
119-
p += tag.get_text()
120-
return p
121-
122-
def mfsa_id_from_filename(self, filename):
123-
match = MFSA_FILENAME_RE.search(filename)
124-
if match:
125-
return "mfsa" + match.group(1)
126-
127-
return None
128-
129-
def get_package_urls(self, pkgs: List[str]) -> List[PackageURL]:
130-
package_urls = [
131-
PackageURL(
132-
type="mozilla",
133-
# pkg is of the form "Firefox ESR 1.21" or "Thunderbird 2.21"
134-
name=pkg.rsplit(None, 1)[0],
135-
version=pkg.rsplit(None, 1)[1],
136-
)
137-
for pkg in pkgs
138-
]
139-
return package_urls
140-
141-
def get_yml_references(self, data: any) -> List[Reference]:
142-
"""
143-
Returns a list of references
144-
Currently only considers the given mfsa as a reference
145-
"""
146-
# FIXME: Needs improvement
147-
# Should we add 'bugs' section in references too?
148-
# Should we add 'impact'/severity of CVE in references too?
149-
# If yes, then fix alpine_linux importer as well
150-
# Otherwise, do we need severity field for adversary as well?
151-
152-
# FIXME: Write a helper for cvssv3.1_qr severity detection ?
153-
severities = ["critical", "low", "high", "medium", "none"]
154-
severity = [{severity in data.get("impact"): severity} for severity in severities][0].get(
155-
True
15685
)
15786

158-
return [
87+
return advisories
88+
89+
90+
def get_advisories_from_md(mfsa_id, lines) -> List[Advisory]:
91+
yamltext, mdtext = split_markdown_front_matter(lines.read())
92+
data = yaml.safe_load(yamltext)
93+
data["mfsa_id"] = mfsa_id
94+
95+
fixed_package_urls = get_package_urls(data.get("fixed_in"))
96+
references = get_yml_references(data)
97+
cves = re.findall(r"CVE-\d+-\d+", yamltext + mdtext, re.IGNORECASE)
98+
for cve in cves:
99+
references.append(
159100
Reference(
160-
reference_id=data["mfsa_id"],
161-
url="https://www.mozilla.org/en-US/security/advisories/{}".format(data["mfsa_id"]),
162-
severities=[VulnerabilitySeverity(scoring_systems["cvssv3.1_qr"], severity)],
101+
reference_id=cve,
102+
url=f"https://cve.mitre.org/cgi-bin/cvename.cgi?name={cve}",
163103
)
164-
]
104+
)
105+
106+
description = html_get_p_under_h3(markdown(mdtext), "description")
107+
108+
return [
109+
Advisory(
110+
summary=description,
111+
vulnerability_id="",
112+
impacted_package_urls=[],
113+
resolved_package_urls=fixed_package_urls,
114+
references=references,
115+
)
116+
]
117+
118+
119+
def html_get_p_under_h3(html, h3: str):
120+
soup = BeautifulSoup(html, features="lxml")
121+
h3tag = soup.find("h3", text=lambda txt: txt.lower() == h3)
122+
p = ""
123+
if h3tag:
124+
for tag in h3tag.next_siblings:
125+
if tag.name:
126+
if tag.name != "p":
127+
break
128+
p += tag.get_text()
129+
return p
130+
131+
132+
def mfsa_id_from_filename(filename):
133+
match = MFSA_FILENAME_RE.search(filename)
134+
if match:
135+
return "mfsa" + match.group(1)
136+
137+
return None
138+
139+
140+
def get_package_urls(pkgs: List[str]) -> List[PackageURL]:
141+
package_urls = [
142+
PackageURL(
143+
type="mozilla",
144+
# pkg is of the form "Firefox ESR 1.21" or "Thunderbird 2.21"
145+
name=pkg.rsplit(None, 1)[0],
146+
version=pkg.rsplit(None, 1)[1],
147+
)
148+
for pkg in pkgs
149+
if pkg
150+
]
151+
return package_urls
152+
153+
154+
def get_yml_references(data: any) -> List[Reference]:
155+
"""
156+
Returns a list of references
157+
Currently only considers the given mfsa as a reference
158+
"""
159+
# FIXME: Needs improvement
160+
# Should we add 'bugs' section in references too?
161+
# Should we add 'impact'/severity of CVE in references too?
162+
# If yes, then fix alpine_linux importer as well
163+
# Otherwise, do we need severity field for adversary as well?
164+
165+
severities = ["critical", "high", "medium", "low", "none"]
166+
severity = "none"
167+
if data.get("impact"):
168+
impact = data.get("impact").lower()
169+
for s in severities:
170+
if s in impact:
171+
severity = s
172+
break
173+
174+
return [
175+
Reference(
176+
reference_id=data["mfsa_id"],
177+
url="https://www.mozilla.org/en-US/security/advisories/{}".format(data["mfsa_id"]),
178+
# severities=[VulnerabilitySeverity(scoring_systems["unspecified"], severity)],
179+
severities=[VulnerabilitySeverity(scoring_systems["cvssv3.1_qr"], severity)],
180+
)
181+
]

0 commit comments

Comments
 (0)