Skip to content

Commit a442302

Browse files
committed
Time travel for githubtags, maven version api importers
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
1 parent 08fbc26 commit a442302

6 files changed

Lines changed: 130 additions & 139 deletions

File tree

vulnerabilities/importers/alpine_linux.py

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -43,40 +43,6 @@
4343
BASE_URL = "https://secdb.alpinelinux.org/"
4444

4545

46-
# def validate_schema(advisory_dict):
47-
# scheme = {
48-
# "distroversion": Regex(r"v\d.\d*"),
49-
# "reponame": str,
50-
# "archs": list,
51-
# "packages": [
52-
# {
53-
# "pkg": {
54-
# "name": str,
55-
# "secfixes": {
56-
# str: Or(
57-
# [
58-
# Or(
59-
# Regex(r"CVE.\d+-\d+", flags=IGNORECASE),
60-
# Regex(r"XSA-\d{3}"),
61-
# Regex(r"ZBX-\d{4}"),
62-
# Regex(r"wnpa-sec-\d{4}-\d{2}"),
63-
# Regex(r"GHSA-.{4}-.{4}-.{4}"),
64-
# )
65-
# ],
66-
# "",
67-
# # FIXME: Remove the None when below issue gets fixed
68-
# # https://gitlab.alpinelinux.org/alpine/infra/alpine-secdb/-/issues/1
69-
# None,
70-
# ),
71-
# },
72-
# }
73-
# }
74-
# ],
75-
# object: object,
76-
# }
77-
# Schema(scheme).validate(advisory_dict)
78-
79-
8046
class AlpineDataSource(DataSource):
8147
@staticmethod
8248
def fetch_advisory_links():

vulnerabilities/importers/elixir_security.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def get_versions_for_pkg_from_range_list(self, version_range_list, pkg_name):
8383

8484
safe_pkg_versions = []
8585
vuln_pkg_versions = []
86-
all_version_list = self.pkg_manager_api.get(pkg_name)
86+
all_version_list = self.pkg_manager_api.get(pkg_name)["valid"]
8787
if not version_range_list:
8888
return [], all_version_list
8989
version_ranges = [

vulnerabilities/importers/istio.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
# VulnerableCode is a free software tool from nexB Inc. and others.
2121
# Visit https://github.com/nexB/vulnerablecode/ for support and download.
2222
import asyncio
23+
import pytz
2324
import re
25+
from dateutil import parser
2426
from typing import Set
2527

2628
import saneyaml
@@ -60,11 +62,11 @@ def updated_advisories(self) -> Set[Advisory]:
6062
advisories.extend(processed_data)
6163
return self.batch_advisories(advisories)
6264

63-
def get_pkg_versions_from_ranges(self, version_range_list):
65+
def get_pkg_versions_from_ranges(self, version_range_list, release_date):
6466
"""Takes a list of version ranges(affected) of a package
6567
as parameter and returns a tuple of safe package versions and
6668
vulnerable package versions"""
67-
all_version = self.version_api.get("istio/istio")
69+
all_version = self.version_api.get("istio/istio", release_date)["valid"]
6870
safe_pkg_versions = []
6971
vuln_pkg_versions = []
7072
version_ranges = [
@@ -123,6 +125,7 @@ def process_file(self, path):
123125
advisories = []
124126

125127
data = self.get_data_from_md(path)
128+
release_date = parser.parse(data["publishdate"]).replace(tzinfo=pytz.UTC)
126129

127130
releases = []
128131
if data.get("releases"):
@@ -165,7 +168,7 @@ def process_file(self, path):
165168
data["release_ranges"] = []
166169

167170
safe_pkg_versions, vuln_pkg_versions = self.get_pkg_versions_from_ranges(
168-
data["release_ranges"]
171+
data["release_ranges"], release_date
169172
)
170173

171174
affected_packages = []

vulnerabilities/importers/nginx.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ def set_api(self):
5353

5454
# For some reason nginx tags it's releases are in the form of `release-1.2.3`
5555
# Chop off the `release-` part here.
56-
for index, version in enumerate(self.version_api.cache["nginx/nginx"]):
57-
self.version_api.cache["nginx/nginx"][index] = version.replace("release-", "")
56+
for index, version in enumerate(self.version_api.cache["nginx/nginx"]["valid"]):
57+
self.version_api.cache["nginx/nginx"]["valid"][index] = version.replace("release-", "")
5858

5959
def updated_advisories(self):
6060
advisories = []
@@ -134,7 +134,9 @@ def extract_fixed_pkgs(self, vuln_info):
134134
VersionSpecifier.from_scheme_version_spec_string("semver", "^" + rng[:-1])
135135
)
136136

137-
valid_versions = find_valid_versions(self.version_api.get("nginx/nginx"), version_ranges)
137+
valid_versions = find_valid_versions(
138+
self.version_api.get("nginx/nginx")["valid"], version_ranges
139+
)
138140

139141
return [
140142
PackageURL(type="generic", name="nginx", version=version) for version in valid_versions
Lines changed: 81 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,95 @@
1-
# Copyright (c) 2017 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 code scanning tool from nexB Inc. and others.
21-
# Visit https://github.com/nexB/vulnerablecode/ for support and download.
22-
import dataclasses
1+
# # Copyright (c) 2017 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 code scanning tool from nexB Inc. and others.
21+
# # Visit https://github.com/nexB/vulnerablecode/ for support and download.
22+
# import dataclasses
2323

24-
import requests
25-
import saneyaml
26-
from bs4 import BeautifulSoup
27-
from packageurl import PackageURL
24+
# import requests
25+
# import saneyaml
26+
# from bs4 import BeautifulSoup
27+
# from packageurl import PackageURL
2828

29-
from vulnerabilities.data_source import Advisory
30-
from vulnerabilities.data_source import DataSource
31-
from vulnerabilities.data_source import DataSourceConfiguration
32-
from vulnerabilities.helpers import create_etag
29+
# from vulnerabilities.data_source import Advisory
30+
# from vulnerabilities.data_source import DataSource
31+
# from vulnerabilities.data_source import DataSourceConfiguration
32+
# from vulnerabilities.helpers import create_etag
3333

3434

35-
@dataclasses.dataclass
36-
class SUSEBackportsConfiguration(DataSourceConfiguration):
37-
url: str
38-
etags: dict
35+
# @dataclasses.dataclass
36+
# class SUSEBackportsConfiguration(DataSourceConfiguration):
37+
# url: str
38+
# etags: dict
3939

4040

41-
class SUSEBackportsDataSource(DataSource):
41+
# class SUSEBackportsDataSource(DataSource):
4242

43-
CONFIG_CLASS = SUSEBackportsConfiguration
43+
# CONFIG_CLASS = SUSEBackportsConfiguration
4444

45-
@staticmethod
46-
def get_all_urls_of_backports(url):
47-
r = requests.get(url)
48-
soup = BeautifulSoup(r.content, "lxml")
49-
for a_tag in soup.find_all("a", href=True):
50-
if a_tag["href"].endswith(".yaml") and a_tag["href"].startswith("backports"):
51-
yield url + a_tag["href"]
45+
# @staticmethod
46+
# def get_all_urls_of_backports(url):
47+
# r = requests.get(url)
48+
# soup = BeautifulSoup(r.content, "lxml")
49+
# for a_tag in soup.find_all("a", href=True):
50+
# if a_tag["href"].endswith(".yaml") and a_tag["href"].startswith("backports"):
51+
# yield url + a_tag["href"]
5252

53-
def updated_advisories(self):
54-
advisories = []
55-
all_urls = self.get_all_urls_of_backports(self.config.url)
56-
for url in all_urls:
57-
if not create_etag(data_src=self, url=url, etag_key="ETag"):
58-
continue
59-
advisories.extend(self.process_file(self._fetch_yaml(url)))
60-
return self.batch_advisories(advisories)
53+
# def updated_advisories(self):
54+
# advisories = []
55+
# all_urls = self.get_all_urls_of_backports(self.config.url)
56+
# for url in all_urls:
57+
# if not create_etag(data_src=self, url=url, etag_key="ETag"):
58+
# continue
59+
# advisories.extend(self.process_file(self._fetch_yaml(url)))
60+
# return self.batch_advisories(advisories)
6161

62-
def _fetch_yaml(self, url):
62+
# def _fetch_yaml(self, url):
6363

64-
try:
65-
resp = requests.get(url)
66-
resp.raise_for_status()
67-
return saneyaml.load(resp.content)
64+
# try:
65+
# resp = requests.get(url)
66+
# resp.raise_for_status()
67+
# return saneyaml.load(resp.content)
6868

69-
except requests.HTTPError:
70-
return {}
69+
# except requests.HTTPError:
70+
# return {}
7171

72-
@staticmethod
73-
def process_file(yaml_file):
74-
advisories = []
75-
try:
76-
for pkg in yaml_file[0]["packages"]:
77-
for version in yaml_file[0]["packages"][pkg]["fixed"]:
78-
for vuln in yaml_file[0]["packages"][pkg]["fixed"][version]:
79-
# yaml_file specific data can be added
80-
purl = [
81-
PackageURL(name=pkg, type="rpm", version=version, namespace="opensuse")
82-
]
83-
advisories.append(
84-
Advisory(
85-
vulnerability_id=vuln,
86-
resolved_package_urls=purl,
87-
summary="",
88-
impacted_package_urls=[],
89-
)
90-
)
91-
except TypeError:
92-
# could've used pass
93-
return advisories
72+
# @staticmethod
73+
# def process_file(yaml_file):
74+
# advisories = []
75+
# try:
76+
# for pkg in yaml_file[0]["packages"]:
77+
# for version in yaml_file[0]["packages"][pkg]["fixed"]:
78+
# for vuln in yaml_file[0]["packages"][pkg]["fixed"][version]:
79+
# # yaml_file specific data can be added
80+
# purl = [
81+
# PackageURL(name=pkg, type="rpm", version=version, namespace="opensuse")
82+
# ]
83+
# advisories.append(
84+
# Advisory(
85+
# vulnerability_id=vuln,
86+
# resolved_package_urls=purl,
87+
# summary="",
88+
# impacted_package_urls=[],
89+
# )
90+
# )
91+
# except TypeError:
92+
# # could've used pass
93+
# return advisories
9494

95-
return advisories
95+
# return advisories

vulnerabilities/package_managers.py

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,16 @@
2222

2323
import asyncio
2424
from collections import namedtuple
25-
import aiohttp
25+
import pytz
2626
from bs4 import BeautifulSoup
2727
from dateutil import parser
2828
from json import JSONDecodeError
2929
from typing import Mapping
3030
from typing import Set
31-
from typing import List
32-
import xml.etree.ElementTree as ET
3331

3432
from aiohttp import ClientSession
3533
from aiohttp.client_exceptions import ClientResponseError
3634
from aiohttp.client_exceptions import ServerDisconnectedError
37-
from requests.sessions import session
3835

3936

4037
Version = namedtuple("Version", field_names=["value", "release_date"])
@@ -255,12 +252,15 @@ class MavenVersionAPI(VersionAPI):
255252
async def load_api(self, pkg_set):
256253
async with client_session() as session:
257254
await asyncio.gather(
258-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
255+
*[
256+
self.fetch(pkg, session)
257+
for pkg in pkg_set
258+
if pkg not in self.cache and "camel" not in pkg
259+
]
259260
)
260261

261262
async def fetch(self, pkg, session) -> None:
262-
artifact_comps = pkg.split(":")
263-
endpoint = self.artifact_url(artifact_comps)
263+
endpoint = self.artifact_url(pkg)
264264
try:
265265
resp = await session.request(method="GET", url=endpoint)
266266
resp = await resp.read()
@@ -269,11 +269,15 @@ async def fetch(self, pkg, session) -> None:
269269
self.cache[pkg] = set()
270270
return
271271

272-
xml_resp = ET.ElementTree(ET.fromstring(resp.decode("utf-8")))
273-
self.cache[pkg] = self.extract_versions(xml_resp)
272+
soup = BeautifulSoup(resp, features="lxml")
273+
try:
274+
self.cache[pkg] = self.extract_versions(soup)
275+
except:
276+
raise
274277

275278
@staticmethod
276-
def artifact_url(artifact_comps: List[str]) -> str:
279+
def artifact_url(pkg: str) -> str:
280+
artifact_comps = pkg.split(":")
277281
base_url = "https://repo1.maven.org/maven2/{}"
278282
try:
279283
group_id, artifact_id = artifact_comps
@@ -289,19 +293,35 @@ def artifact_url(artifact_comps: List[str]) -> str:
289293
raise
290294

291295
group_url = group_id.replace(".", "/")
292-
suffix = group_url + "/" + artifact_id + "/" + "maven-metadata.xml"
296+
suffix = group_url + "/" + artifact_id + "/"
293297
endpoint = base_url.format(suffix)
294298

295299
return endpoint
296300

297301
@staticmethod
298-
def extract_versions(xml_response: ET.ElementTree) -> Set[str]:
299-
all_versions = set()
300-
for child in xml_response.getroot().iter():
301-
if child.tag == "version":
302-
all_versions.add(child.text)
302+
def extract_versions(soup: BeautifulSoup) -> Set[Version]:
303+
pre_tag = soup.find("pre")
304+
prev_tag = None
305+
versions = set()
306+
for atag in pre_tag:
307+
if atag.name == "a" and atag["href"] != "../":
308+
prev_tag = atag
309+
elif prev_tag:
310+
text_groups = atag.split()
311+
if text_groups[-1] != "-":
312+
break
313+
date = " ".join(text_groups[:-1])
314+
if date != "-":
315+
versions.add(
316+
Version(
317+
value=prev_tag.text[:-1],
318+
release_date=parser.parse(date).replace(tzinfo=pytz.UTC),
319+
)
320+
)
321+
else:
322+
versions.add(Version(value=prev_tag.text[:-1], release_date=None))
303323

304-
return all_versions
324+
return versions
305325

306326

307327
class NugetVersionAPI(VersionAPI):

0 commit comments

Comments
 (0)