Skip to content

Commit 4b89ef1

Browse files
committed
➕ Add Apache HTTPD advisory importer
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
1 parent 8efdbd1 commit 4b89ef1

3 files changed

Lines changed: 116 additions & 0 deletions

File tree

vulnerabilities/importer_yielder.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,15 @@
189189
'data_source': 'ProjectKBMSRDataSource',
190190
'data_source_cfg': {
191191
'etag': {}
192+
}
193+
},
194+
{
195+
'name': 'apache_httpd',
196+
'license': '',
197+
'last_run': None,
198+
'data_source': 'ApacheHTTPDDataSource',
199+
'data_source_cfg': {
200+
'etags': {}
192201
},
193202
},
194203

vulnerabilities/importers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@
3939
from vulnerabilities.importers.github import GitHubAPIDataSource
4040
from vulnerabilities.importers.nvd import NVDDataSource
4141
from vulnerabilities.importers.project_kb_msr2019 import ProjectKBMSRDataSource
42+
from vulnerabilities.importers.apache_httpd import ApacheHTTPDDataSource
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
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+
from dataclasses import dataclass
24+
import xml.etree.ElementTree as ET
25+
26+
import requests
27+
from packageurl import PackageURL
28+
29+
from vulnerabilities.data_source import Advisory
30+
from vulnerabilities.data_source import DataSource
31+
from vulnerabilities.data_source import DataSourceConfiguration
32+
33+
34+
@dataclass
35+
class ApacheHTTPDDataSourceConfiguration(DataSourceConfiguration):
36+
etags: dict
37+
38+
39+
class ApacheHTTPDDataSource(DataSource):
40+
41+
CONFIG_CLASS = ApacheHTTPDDataSourceConfiguration
42+
url = "https://httpd.apache.org/security/vulnerabilities-httpd.xml"
43+
44+
def updated_advisories(self):
45+
# Etags are like hashes of web responses. We maintain
46+
# (url, etag) mappings in the DB. `create_etag` creates
47+
# (url, etag) pair. If a (url, etag) already exists then the code
48+
# skips processing the response further to avoid duplicate work
49+
50+
if self.create_etag(self.url):
51+
data = fetch_xml(self.url)
52+
advisories = to_advisories(data)
53+
return self.batch_advisories(advisories)
54+
55+
return []
56+
57+
def create_etag(self, url):
58+
etag = requests.head(url).headers.get("ETag")
59+
if not etag:
60+
return True
61+
62+
elif url in self.config.etags:
63+
if self.config.etags[url] == etag:
64+
return False
65+
66+
self.config.etags[url] = etag
67+
return True
68+
69+
70+
def to_advisories(data):
71+
advisories = []
72+
for issue in data:
73+
resolved_packages = []
74+
impacted_packages = []
75+
for info in issue:
76+
if info.tag == "cve":
77+
cve = info.attrib["name"]
78+
79+
if info.tag == "title":
80+
summary = info.text
81+
82+
if info.tag == "fixed":
83+
resolved_packages.append(
84+
PackageURL(name="httpd", version=info.attrib["version"], type="generic")
85+
)
86+
87+
if info.tag == "affects" or info.tag == "maybeaffects":
88+
impacted_packages.append(
89+
PackageURL(name="httpd", version=info.attrib["version"], type="generic")
90+
)
91+
92+
advisories.append(
93+
Advisory(
94+
cve_id=cve,
95+
summary=summary,
96+
impacted_package_urls=impacted_packages,
97+
resolved_package_urls=resolved_packages,
98+
)
99+
)
100+
101+
return advisories
102+
103+
104+
def fetch_xml(url):
105+
resp = requests.get(url).content
106+
return ET.fromstring(resp)

0 commit comments

Comments
 (0)