Skip to content

Commit 379703a

Browse files
committed
Add postgresql advisories importer
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
1 parent 0e760ad commit 379703a

3 files changed

Lines changed: 129 additions & 0 deletions

File tree

vulnerabilities/importer_yielder.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@
200200
'etag': {}
201201
},
202202
},
203+
{
204+
'name': 'postgresql',
205+
'license': '',
206+
'last_run': None,
207+
'data_source': 'PostgreSQLDataSource',
208+
'data_source_cfg': {},
209+
},
203210

204211
]
205212

vulnerabilities/importers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@
4040
from vulnerabilities.importers.nvd import NVDDataSource
4141
from vulnerabilities.importers.project_kb_msr2019 import ProjectKBMSRDataSource
4242
from vulnerabilities.importers.nginx import NginxDataSource
43+
from vulnerabilities.importers.postgresql import PostgreSQLDataSource
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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 from nexB Inc. and others.
21+
# Visit https://github.com/nexB/vulnerablecode/ for support and download.
22+
23+
import dataclasses
24+
25+
from bs4 import BeautifulSoup
26+
from packageurl import PackageURL
27+
import requests
28+
from urllib.parse import urljoin
29+
30+
from vulnerabilities.data_source import Advisory
31+
from vulnerabilities.data_source import DataSource
32+
from vulnerabilities.data_source import Reference
33+
34+
BASE_URL = "https://www.postgresql.org/"
35+
36+
37+
class PostgreSQLDataSource(DataSource):
38+
39+
root_url = "https://www.postgresql.org/support/security/"
40+
41+
def updated_advisories(self):
42+
advisories = []
43+
known_urls = {self.root_url}
44+
visited_urls = set()
45+
while True:
46+
unvisited_urls = known_urls - visited_urls
47+
for url in unvisited_urls:
48+
data = requests.get(url).content
49+
advisories.extend(to_advisories(data))
50+
visited_urls.add(url)
51+
known_urls.update(find_advisory_urls(data))
52+
53+
if known_urls == visited_urls:
54+
break
55+
56+
return self.batch_advisories(advisories)
57+
58+
59+
def to_advisories(data):
60+
advisories = []
61+
soup = BeautifulSoup(data)
62+
table = soup.select("table")[0]
63+
for row in table.select("tbody tr"):
64+
ref_col, affected_col, fixed_col, severity_score_col, desc_col = row.select("td")
65+
summary = desc_col.text
66+
pkg_qualifiers = {}
67+
if "windows" in summary.lower():
68+
pkg_qualifiers = {"os": "windows"}
69+
70+
affected_packages = [
71+
PackageURL(
72+
type="generic",
73+
name="postgresql",
74+
version=version.strip(),
75+
qualifiers=pkg_qualifiers,
76+
)
77+
for version in affected_col.text.split(",")
78+
]
79+
80+
fixed_packages = [
81+
PackageURL(
82+
type="generic",
83+
name="postgresql",
84+
version=version.strip(),
85+
qualifiers=pkg_qualifiers,
86+
)
87+
for version in fixed_col.text.split(",")
88+
]
89+
90+
try:
91+
cve_id = ref_col.select("nobr")[0].text
92+
# This is for the anomaly in https://www.postgresql.org/support/security/8.1/ 's
93+
# last entry
94+
except IndexError:
95+
pass
96+
97+
references = []
98+
for a_tag in ref_col.select("a"):
99+
link = a_tag.attrs["href"]
100+
if link.startswith("/about/news/"):
101+
# Convert postgresql official announcements to absolute url.
102+
link = urljoin(BASE_URL, link)
103+
104+
references.append(Reference(url=link))
105+
106+
advisories.append(
107+
Advisory(
108+
cve_id=cve_id,
109+
summary=summary,
110+
vuln_references=references,
111+
impacted_package_urls=affected_packages,
112+
resolved_package_urls=fixed_packages,
113+
)
114+
)
115+
116+
return advisories
117+
118+
119+
def find_advisory_urls(page_data):
120+
soup = BeautifulSoup(page_data)
121+
return {urljoin(BASE_URL, a_tag.attrs["href"]) for a_tag in soup.select("h3+ p a")}

0 commit comments

Comments
 (0)