Skip to content

Commit bcdee7d

Browse files
committed
Add apache kafka advisory importer
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
1 parent 837bb8f commit bcdee7d

3 files changed

Lines changed: 128 additions & 0 deletions

File tree

vulnerabilities/importer_yielder.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,13 @@
241241
"etags": {}
242242
},
243243
},
244+
{
245+
'name': 'apache_kafka',
246+
'license': '',
247+
'last_run': None,
248+
'data_source': 'ApacheKafkaDataSource',
249+
'data_source_cfg': {},
250+
},
244251

245252
]
246253

vulnerabilities/importers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@
4545
from vulnerabilities.importers.ubuntu import UbuntuDataSource
4646
from vulnerabilities.importers.ubuntu_usn import UbuntuUSNDataSource
4747
from vulnerabilities.importers.apache_tomcat import ApacheTomcatDataSource
48+
from vulnerabilities.importers.apache_kafka import ApacheKafkaDataSource
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Copyright (c) nexB Inc. and others. All rights reserved.
2+
# http://nexb.com and https://github.com/nexB/vulnerablecode/
3+
# The VulnerableCode software is licensed under the Apache License version 2.0.
4+
# Data generated with VulnerableCode require an acknowledgment.
5+
#
6+
# You may not use this software except in compliance with the License.
7+
# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
8+
# Unless required by applicable law or agreed to in writing, software distributed
9+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
# specific language governing permissions and limitations under the License.
12+
#
13+
# When you publish or redistribute any data created with VulnerableCode or any VulnerableCode
14+
# derivative work, you must accompany this data with the following acknowledgment:
15+
#
16+
# Generated with VulnerableCode and provided on an "AS IS" BASIS, WITHOUT WARRANTIES
17+
# OR CONDITIONS OF ANY KIND, either express or implied. No content created from
18+
# VulnerableCode should be considered or used as legal advice. Consult an Attorney
19+
# for any legal advice.
20+
# VulnerableCode is a free software tool from nexB Inc. and others.
21+
# Visit https://github.com/nexB/vulnerablecode/ for support and download.
22+
23+
import asyncio
24+
25+
import requests
26+
from bs4 import BeautifulSoup
27+
from dephell_specifier import RangeSpecifier
28+
from packageurl import PackageURL
29+
30+
from vulnerabilities.data_source import Advisory, DataSource, Reference
31+
from vulnerabilities.package_managers import GitHubTagsAPI
32+
33+
GH_PAGE_URL = "https://raw.githubusercontent.com/apache/kafka-site/asf-site/cve-list.html"
34+
ASF_PAGE_URL = "https://kafka.apache.org/cve-list"
35+
36+
37+
class ApacheKafkaDataSource(DataSource):
38+
@staticmethod
39+
def fetch_advisory_page():
40+
page = requests.get(GH_PAGE_URL)
41+
return page.content
42+
43+
def set_api(self):
44+
self.version_api = GitHubTagsAPI()
45+
asyncio.run(self.version_api.load_api(["apache/kafka"]))
46+
47+
def updated_advisories(self):
48+
advisory_page = self.fetch_advisory_page()
49+
self.set_api()
50+
parsed_data = self.to_advisory(advisory_page)
51+
return self.batch_advisories(parsed_data)
52+
53+
def to_advisory(self, advisory_page):
54+
advisories = []
55+
advisory_page = BeautifulSoup(advisory_page, features="lxml")
56+
cve_section_beginnings = advisory_page.find_all("h2")
57+
for cve_section_beginning in cve_section_beginnings:
58+
cve_id = cve_section_beginning.text.split("\n")[0]
59+
cve_description_paragraph = cve_section_beginning.find_next_sibling("p")
60+
cve_data_table = cve_section_beginning.find_next_sibling("table")
61+
cve_data_table_rows = cve_data_table.find_all("tr")
62+
affected_versions_row, fixed_versions_row = (
63+
cve_data_table_rows[0],
64+
cve_data_table_rows[1],
65+
)
66+
affected_version_ranges = to_version_ranges(
67+
affected_versions_row.find_all("td")[1].text
68+
)
69+
fixed_version_ranges = to_version_ranges(fixed_versions_row.find_all("td")[1].text)
70+
71+
fixed_packages = [
72+
PackageURL(type="apache", name="kafka", version=version)
73+
for version in self.version_api.get("apache/kafka")
74+
if any([version in version_range for version_range in fixed_version_ranges])
75+
]
76+
77+
affected_packages = [
78+
PackageURL(type="apache", name="kafka", version=version)
79+
for version in self.version_api.get("apache/kafka")
80+
if any([version in version_range for version_range in affected_version_ranges])
81+
]
82+
83+
advisories.append(
84+
Advisory(
85+
cve_id=cve_id,
86+
summary=cve_description_paragraph.text,
87+
impacted_package_urls=affected_packages,
88+
resolved_package_urls=fixed_packages,
89+
vuln_references=[
90+
Reference(url=ASF_PAGE_URL),
91+
Reference(
92+
url=f"https://cve.mitre.org/cgi-bin/cvename.cgi?name={cve_id}",
93+
reference_id=cve_id,
94+
),
95+
],
96+
)
97+
)
98+
return advisories
99+
100+
101+
def to_version_ranges(version_range_text):
102+
version_ranges = []
103+
range_expressions = version_range_text.split(",")
104+
for range_expression in range_expressions:
105+
if "to" in range_expression:
106+
# eg range_expression == "3.2.0 to 3.2.1"
107+
lower_bound, upper_bound = range_expression.split("to")
108+
lower_bound = f">={lower_bound}"
109+
upper_bound = f"<={upper_bound}"
110+
version_ranges.append(RangeSpecifier(f"{lower_bound},{upper_bound}"))
111+
112+
elif "and later" in range_expression:
113+
# eg range_expression == "2.1.1 and later"
114+
range_expression = range_expression.replace("and later", "")
115+
version_ranges.append(RangeSpecifier(f">={range_expression}"))
116+
117+
else:
118+
# eg range_expression == "3.0.0"
119+
version_ranges.append(RangeSpecifier(range_expression))
120+
return version_ranges

0 commit comments

Comments
 (0)