Skip to content

Commit f4014ae

Browse files
authored
Merge branch 'main' into merge_api_tests
2 parents 9aa25c1 + 13427e1 commit f4014ae

File tree

102 files changed

+5077
-2450
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+5077
-2450
lines changed

CHANGELOG.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,25 @@ Release notes
22
=============
33

44

5-
Next release
6-
----------------
5+
Version v32.0.0rc2
6+
--------------------
7+
8+
- We added migration for adding apache tomcat option in severity scoring.
9+
10+
11+
Version v32.0.0rc1
12+
--------------------
713

814
- We re-enabled support for the mozilla vulnerabilities advisories importer.
915
- We re-enabled support for the gentoo vulnerabilities advisories importer.
1016
- We re-enabled support for the istio vulnerabilities advisories importer.
1117
- We re-enabled support for the kbmsr2019 vulnerabilities advisories importer.
1218
- We re-enabled support for the suse score advisories importer.
1319
- We re-enabled support for the elixir security advisories importer.
20+
- We re-enabled support for the apache tomcat security advisories importer.
21+
- We added support for CWE.
22+
- We added migrations to remove corrupted advisories https://github.com/nexB/vulnerablecode/issues/1086.
23+
1424

1525
Version v31.1.1
1626
---------------

requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ beautifulsoup4==4.10.0
1111
binaryornot==0.4.4
1212
black==22.3.0
1313
boolean.py==3.8
14-
certifi==2021.10.8
14+
certifi==2022.12.7
1515
cffi==1.15.0
1616
chardet==4.0.0
1717
charset-normalizer==2.0.12
@@ -36,7 +36,7 @@ executing==0.8.3
3636
freezegun==1.2.1
3737
frozenlist==1.3.0
3838
gitdb==4.0.9
39-
GitPython==3.1.27
39+
GitPython==3.1.30
4040
gunicorn==20.1.0
4141
idna==3.3
4242
imagesize==1.3.0
@@ -115,7 +115,7 @@ yarl==1.7.2
115115
zipp==3.8.0
116116
dateparser==1.1.1
117117
fetchcode==0.2.0
118-
118+
cwe2==2.0.0
119119
drf-spectacular-sidecar==2022.10.1
120120
drf-spectacular==0.24.2
121121
coreapi==2.3.3

setup.cfg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = vulnerablecode
3-
version = 31.1.1
3+
version = 32.0.0rc2
44
license = Apache-2.0 AND CC-BY-SA-4.0
55

66
# description must be on ONE line https://github.com/pypa/setuptools/issues/1390
@@ -84,6 +84,7 @@ install_requires =
8484
Markdown>=3.3.0
8585
dateparser>=1.1.1
8686
cvss>=2.4
87+
cwe2>=2.0.0
8788

8889
# networking
8990
GitPython>=3.1.17

vulnerabilities/import_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def process_advisories(advisory_datas: Iterable[AdvisoryData], importer_name: st
6161
affected_packages=[pkg.to_dict() for pkg in data.affected_packages],
6262
references=[ref.to_dict() for ref in data.references],
6363
date_published=data.date_published,
64+
weaknesses=data.weaknesses,
6465
defaults={
6566
"created_by": importer_name,
6667
"date_collected": datetime.datetime.now(tz=datetime.timezone.utc),

vulnerabilities/importer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ class AdvisoryData:
246246
affected_packages: List[AffectedPackage] = dataclasses.field(default_factory=list)
247247
references: List[Reference] = dataclasses.field(default_factory=list)
248248
date_published: Optional[datetime.datetime] = None
249+
weaknesses: List[int] = dataclasses.field(default_factory=list)
249250

250251
def __post_init__(self):
251252
if self.date_published and not self.date_published.tzinfo:
@@ -258,6 +259,7 @@ def to_dict(self):
258259
"affected_packages": [pkg.to_dict() for pkg in self.affected_packages],
259260
"references": [ref.to_dict() for ref in self.references],
260261
"date_published": self.date_published.isoformat() if self.date_published else None,
262+
"weaknesses": self.weaknesses,
261263
}
262264

263265
@classmethod
@@ -273,6 +275,7 @@ def from_dict(cls, advisory_data):
273275
"date_published": datetime.datetime.fromisoformat(date_published)
274276
if date_published
275277
else None,
278+
"weaknesses": advisory_data["weaknesses"],
276279
}
277280
return cls(**transformed)
278281

vulnerabilities/importers/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
from vulnerabilities.importers import retiredotnet
3232
from vulnerabilities.importers import suse_scores
3333
from vulnerabilities.importers import ubuntu
34+
from vulnerabilities.importers import ubuntu_usn
35+
from vulnerabilities.importers import xen
3436

3537
IMPORTERS_REGISTRY = [
3638
nginx.NginxImporter,
@@ -57,6 +59,8 @@
5759
suse_scores.SUSESeverityScoreImporter,
5860
elixir_security.ElixirSecurityImporter,
5961
apache_tomcat.ApacheTomcatImporter,
62+
xen.XenImporter,
63+
ubuntu_usn.UbuntuUSNImporter,
6064
]
6165

6266
IMPORTERS_REGISTRY = {x.qualified_name: x for x in IMPORTERS_REGISTRY}

vulnerabilities/importers/apache_httpd.py

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10-
import asyncio
10+
import logging
1111
import urllib
12+
from datetime import datetime
13+
from typing import Iterable
14+
from typing import List
15+
from typing import Mapping
16+
from typing import Optional
1217

1318
import requests
1419
from bs4 import BeautifulSoup
20+
from django.db.models.query import QuerySet
1521
from packageurl import PackageURL
1622
from univers.version_constraint import VersionConstraint
1723
from univers.version_range import ApacheVersionRange
@@ -21,8 +27,20 @@
2127
from vulnerabilities.importer import AffectedPackage
2228
from vulnerabilities.importer import Importer
2329
from vulnerabilities.importer import Reference
30+
from vulnerabilities.importer import UnMergeablePackageError
2431
from vulnerabilities.importer import VulnerabilitySeverity
32+
from vulnerabilities.improver import Improver
33+
from vulnerabilities.improver import Inference
34+
from vulnerabilities.models import Advisory
35+
from vulnerabilities.package_managers import GitHubTagsAPI
36+
from vulnerabilities.package_managers import VersionAPI
2537
from vulnerabilities.severity_systems import APACHE_HTTPD
38+
from vulnerabilities.utils import AffectedPackage as LegacyAffectedPackage
39+
from vulnerabilities.utils import get_affected_packages_by_patched_package
40+
from vulnerabilities.utils import nearest_patched_package
41+
from vulnerabilities.utils import resolve_version_range
42+
43+
logger = logging.getLogger(__name__)
2644

2745

2846
class ApacheHTTPDImporter(Importer):
@@ -147,7 +165,7 @@ def fetch_links(url):
147165
return links
148166

149167

150-
ignore_tags = {
168+
IGNORE_TAGS = {
151169
"AGB_BEFORE_AAA_CHANGES",
152170
"APACHE_1_2b1",
153171
"APACHE_1_2b10",
@@ -209,3 +227,80 @@ def fetch_links(url):
209227
"post_ajp_proxy",
210228
"pre_ajp_proxy",
211229
}
230+
231+
232+
class ApacheHTTPDImprover(Improver):
233+
def __init__(self) -> None:
234+
self.versions_fetcher_by_purl: Mapping[str, VersionAPI] = {}
235+
self.vesions_by_purl = {}
236+
237+
@property
238+
def interesting_advisories(self) -> QuerySet:
239+
return Advisory.objects.filter(created_by=ApacheHTTPDImporter.qualified_name)
240+
241+
def get_package_versions(
242+
self, package_url: PackageURL, until: Optional[datetime] = None
243+
) -> List[str]:
244+
"""
245+
Return a list of `valid_versions` for the `package_url`
246+
"""
247+
api_name = "apache/httpd"
248+
versions_fetcher = GitHubTagsAPI()
249+
return versions_fetcher.get_until(package_name=api_name, until=until).valid_versions
250+
251+
def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
252+
"""
253+
Yield Inferences for the given advisory data
254+
"""
255+
if not advisory_data.affected_packages:
256+
return
257+
try:
258+
purl, affected_version_ranges, _ = AffectedPackage.merge(
259+
advisory_data.affected_packages
260+
)
261+
except UnMergeablePackageError:
262+
logger.error(f"Cannot merge with different purls {advisory_data.affected_packages!r}")
263+
return iter([])
264+
265+
pkg_type = purl.type
266+
pkg_namespace = purl.namespace
267+
pkg_name = purl.name
268+
269+
if not self.vesions_by_purl.get(str(purl)):
270+
valid_versions = self.get_package_versions(
271+
package_url=purl, until=advisory_data.date_published
272+
)
273+
self.vesions_by_purl[str(purl)] = valid_versions
274+
275+
valid_versions = self.vesions_by_purl[str(purl)]
276+
277+
for affected_version_range in affected_version_ranges:
278+
aff_vers, unaff_vers = resolve_version_range(
279+
affected_version_range=affected_version_range,
280+
package_versions=valid_versions,
281+
ignorable_versions=IGNORE_TAGS,
282+
)
283+
affected_purls = [
284+
PackageURL(type=pkg_type, namespace=pkg_namespace, name=pkg_name, version=version)
285+
for version in aff_vers
286+
]
287+
288+
unaffected_purls = [
289+
PackageURL(type=pkg_type, namespace=pkg_namespace, name=pkg_name, version=version)
290+
for version in unaff_vers
291+
]
292+
293+
affected_packages: List[LegacyAffectedPackage] = nearest_patched_package(
294+
vulnerable_packages=affected_purls, resolved_packages=unaffected_purls
295+
)
296+
297+
for (
298+
fixed_package,
299+
affected_packages,
300+
) in get_affected_packages_by_patched_package(affected_packages).items():
301+
yield Inference.from_advisory_data(
302+
advisory_data,
303+
confidence=100, # We are getting all valid versions to get this inference
304+
affected_purls=affected_packages,
305+
fixed_purl=fixed_package,
306+
)

vulnerabilities/importers/istio.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@
66
# See https://github.com/nexB/vulnerablecode for support or download.
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
9+
import logging
910
import re
11+
from datetime import datetime
1012
from pathlib import Path
13+
from typing import Iterable
14+
from typing import List
15+
from typing import Mapping
16+
from typing import Optional
1117
from typing import Set
1218

1319
import pytz
1420
import saneyaml
1521
from dateutil import parser
22+
from django.db.models.query import QuerySet
1623
from packageurl import PackageURL
1724
from univers.version_constraint import VersionConstraint
1825
from univers.version_range import GitHubVersionRange
@@ -23,10 +30,22 @@
2330
from vulnerabilities.importer import AffectedPackage
2431
from vulnerabilities.importer import Importer
2532
from vulnerabilities.importer import Reference
33+
from vulnerabilities.importer import UnMergeablePackageError
34+
from vulnerabilities.improver import Improver
35+
from vulnerabilities.improver import Inference
36+
from vulnerabilities.models import Advisory
37+
from vulnerabilities.package_managers import GitHubTagsAPI
38+
from vulnerabilities.package_managers import VersionAPI
39+
from vulnerabilities.utils import AffectedPackage as LegacyAffectedPackage
40+
from vulnerabilities.utils import get_affected_packages_by_patched_package
41+
from vulnerabilities.utils import nearest_patched_package
42+
from vulnerabilities.utils import resolve_version_range
2643
from vulnerabilities.utils import split_markdown_front_matter
2744

2845
is_release = re.compile(r"^[\d.]+$", re.IGNORECASE).match
2946

47+
logger = logging.getLogger(__name__)
48+
3049

3150
class IstioImporter(Importer):
3251
spdx_license_expression = "Apache-2.0"
@@ -136,3 +155,70 @@ def get_data_from_md(self, path):
136155
with open(path) as f:
137156
front_matter, _ = split_markdown_front_matter(f.read())
138157
return saneyaml.load(front_matter)
158+
159+
160+
class IstioImprover(Improver):
161+
def __init__(self) -> None:
162+
self.versions_fetcher_by_purl: Mapping[str, VersionAPI] = {}
163+
self.vesions_by_purl = {}
164+
165+
@property
166+
def interesting_advisories(self) -> QuerySet:
167+
return Advisory.objects.filter(created_by=IstioImporter.qualified_name)
168+
169+
def get_package_versions(
170+
self, package_url: PackageURL, until: Optional[datetime] = None
171+
) -> List[str]:
172+
"""
173+
Return a list of `valid_versions` for the `package_url`
174+
"""
175+
api_name = "istio/istio"
176+
versions_fetcher = GitHubTagsAPI()
177+
return versions_fetcher.get_until(package_name=api_name, until=until).valid_versions
178+
179+
def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
180+
"""
181+
Yield Inferences for the given advisory data
182+
"""
183+
if not advisory_data.affected_packages:
184+
return
185+
for affected_package in advisory_data.affected_packages:
186+
purl = affected_package.package
187+
affected_version_range = affected_package.affected_version_range
188+
pkg_type = purl.type
189+
pkg_namespace = purl.namespace
190+
pkg_name = purl.name
191+
if not self.vesions_by_purl.get("istio/istio"):
192+
valid_versions = self.get_package_versions(
193+
package_url=purl, until=advisory_data.date_published
194+
)
195+
self.vesions_by_purl["istio/istio"] = valid_versions
196+
valid_versions = self.vesions_by_purl["istio/istio"]
197+
aff_vers, unaff_vers = resolve_version_range(
198+
affected_version_range=affected_version_range,
199+
package_versions=valid_versions,
200+
)
201+
affected_purls = [
202+
PackageURL(type=pkg_type, namespace=pkg_namespace, name=pkg_name, version=version)
203+
for version in aff_vers
204+
]
205+
206+
unaffected_purls = [
207+
PackageURL(type=pkg_type, namespace=pkg_namespace, name=pkg_name, version=version)
208+
for version in unaff_vers
209+
]
210+
211+
affected_packages: List[LegacyAffectedPackage] = nearest_patched_package(
212+
vulnerable_packages=affected_purls, resolved_packages=unaffected_purls
213+
)
214+
215+
for (
216+
fixed_package,
217+
affected_packages,
218+
) in get_affected_packages_by_patched_package(affected_packages).items():
219+
yield Inference.from_advisory_data(
220+
advisory_data,
221+
confidence=100, # We are getting all valid versions to get this inference
222+
affected_purls=affected_packages,
223+
fixed_purl=fixed_package,
224+
)

0 commit comments

Comments
 (0)