Skip to content

Commit 7a48fa3

Browse files
committed
Migrate RetireDotnet to Advisory V2
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
1 parent 15d338c commit 7a48fa3

File tree

5 files changed

+246
-0
lines changed

5 files changed

+246
-0
lines changed

vulnerabilities/importers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
from vulnerabilities.pipelines.v2_importers import pypa_importer as pypa_importer_v2
7474
from vulnerabilities.pipelines.v2_importers import pysec_importer as pysec_importer_v2
7575
from vulnerabilities.pipelines.v2_importers import redhat_importer as redhat_importer_v2
76+
from vulnerabilities.pipelines.v2_importers import retiredotnet_importer as retiredotnet_importer_v2
7677
from vulnerabilities.pipelines.v2_importers import ruby_importer as ruby_importer_v2
7778
from vulnerabilities.pipelines.v2_importers import vulnrichment_importer as vulnrichment_importer_v2
7879
from vulnerabilities.pipelines.v2_importers import xen_importer as xen_importer_v2
@@ -107,6 +108,7 @@
107108
debian_importer_v2.DebianImporterPipeline,
108109
mattermost_importer_v2.MattermostImporterPipeline,
109110
apache_tomcat_v2.ApacheTomcatImporterPipeline,
111+
retiredotnet_importer_v2.RetireDotnetImporterPipeline,
110112
nvd_importer.NVDImporterPipeline,
111113
github_importer.GitHubAPIImporterPipeline,
112114
gitlab_importer.GitLabImporterPipeline,
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
import json
11+
import operator
12+
import re
13+
from itertools import groupby
14+
from pathlib import Path
15+
16+
from fetchcode.vcs import fetch_via_vcs
17+
from packageurl import PackageURL
18+
from univers.version_range import NugetVersionRange
19+
20+
from vulnerabilities.importer import AdvisoryData
21+
from vulnerabilities.importer import AffectedPackageV2
22+
from vulnerabilities.importer import ReferenceV2
23+
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2
24+
from vulnerabilities.utils import get_advisory_url
25+
26+
27+
class RetireDotnetImporterPipeline(VulnerableCodeBaseImporterPipelineV2):
28+
license_url = "https://github.com/RetireNet/Packages/blob/master/LICENSE"
29+
spdx_license_expression = "MIT"
30+
repo_url = "git+https://github.com/RetireNet/Packages/"
31+
pipeline_id = "retiredotnet_importer_v2"
32+
33+
@classmethod
34+
def steps(cls):
35+
return (
36+
cls.clone,
37+
cls.collect_and_store_advisories,
38+
cls.clean_downloads,
39+
)
40+
41+
def clone(self):
42+
self.log(f"Cloning `{self.repo_url}`")
43+
self.vcs_response = fetch_via_vcs(self.repo_url)
44+
45+
def advisories_count(self):
46+
root = Path(self.vcs_response.dest_dir) / "Content"
47+
return sum(1 for _ in root.rglob("*.json"))
48+
49+
def collect_advisories(self):
50+
base_path = Path(self.vcs_response.dest_dir)
51+
vuln = base_path / "Content"
52+
affected_packages = []
53+
54+
for file in vuln.glob("*.json"):
55+
advisory_id = "RetireNet-" + file.stem
56+
advisory_url = get_advisory_url(
57+
file=file,
58+
base_path=base_path,
59+
url="https://github.com/RetireNet/Packages/blob/master/",
60+
)
61+
with open(file) as f:
62+
json_doc = json.load(f)
63+
description = json_doc.get("description") or ""
64+
aliases = self.vuln_id_from_desc(description)
65+
66+
# group by package name `id`
67+
packages = json_doc.get("packages") or []
68+
key_func = operator.itemgetter("id")
69+
packages.sort(key=key_func)
70+
grouped_packages = groupby(packages, key=key_func)
71+
72+
for key, group in grouped_packages:
73+
affected_versions = []
74+
fixed_versions = []
75+
76+
for pkg in list(group):
77+
name = pkg.get("id")
78+
if not name:
79+
continue
80+
81+
affected_version = pkg.get("affected")
82+
if affected_version:
83+
affected_versions.append(affected_version)
84+
85+
fixed_version = pkg.get("fix")
86+
if fixed_version:
87+
fixed_versions.append(fixed_version)
88+
89+
affected_version_range = None
90+
if affected_versions:
91+
affected_version_range = NugetVersionRange.from_versions(affected_versions)
92+
93+
fixed_version_range = None
94+
if fixed_versions:
95+
fixed_version_range = NugetVersionRange.from_versions(affected_versions)
96+
97+
if affected_packages:
98+
affected_packages.append(
99+
AffectedPackageV2(
100+
package=PackageURL(type="nuget", name=name),
101+
affected_version_range=affected_version_range,
102+
fixed_version_range=fixed_version_range,
103+
)
104+
)
105+
106+
link = json_doc.get("link")
107+
if link:
108+
vuln_reference = [
109+
ReferenceV2(
110+
url=link,
111+
)
112+
]
113+
114+
yield AdvisoryData(
115+
advisory_id=advisory_id,
116+
aliases=[aliases] if aliases else [],
117+
summary=description,
118+
affected_packages=affected_packages,
119+
references_v2=vuln_reference,
120+
url=advisory_url,
121+
)
122+
123+
@staticmethod
124+
def vuln_id_from_desc(desc):
125+
cve_regex = re.compile(r"CVE-\d+-\d+")
126+
res = cve_regex.search(desc)
127+
if res:
128+
return desc[res.start() : res.end()]
129+
else:
130+
return None
131+
132+
def clean_downloads(self):
133+
"""Cleanup any temporary repository data."""
134+
if self.vcs_response:
135+
self.log(f"Removing cloned repository")
136+
self.vcs_response.delete()
137+
138+
def on_failure(self):
139+
"""Ensure cleanup is always performed on failure."""
140+
self.clean_downloads()
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
from pathlib import Path
11+
from unittest.mock import Mock
12+
from unittest.mock import patch
13+
14+
import pytest
15+
16+
from vulnerabilities.pipelines.v2_importers.retiredotnet_importer import (
17+
RetireDotnetImporterPipeline,
18+
)
19+
from vulnerabilities.tests import util_tests
20+
21+
TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "retiredotnet_v2"
22+
23+
24+
def test_vuln_id_from_desc():
25+
importer = RetireDotnetImporterPipeline()
26+
gibberish = "xyzabcpqr123" * 50 + "\n" * 100
27+
res = importer.vuln_id_from_desc(gibberish)
28+
assert res is None
29+
30+
desc = "abcdef CVE-2002-1968 pqrstuvwxyz:_|-|"
31+
res = importer.vuln_id_from_desc(desc)
32+
assert res == "CVE-2002-1968"
33+
34+
35+
@pytest.mark.django_db
36+
def test_retiredotnet_advisories_per_file():
37+
pipeline = RetireDotnetImporterPipeline()
38+
test_file = TEST_DATA / "1.json"
39+
expected_file = TEST_DATA / "expected_file.json"
40+
pipeline.vcs_response = Mock(dest_dir=TEST_DATA)
41+
42+
with patch.object(Path, "glob", return_value=[test_file]):
43+
result = [adv.to_dict() for adv in pipeline.collect_advisories()]
44+
45+
util_tests.check_results_against_json(result, expected_file)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"link": "https://github.com/aspnet/Announcements/issues/359",
3+
"description": "Microsoft Security Advisory CVE-2019-0982: ASP.NET Core Denial of Service Vulnerability",
4+
"packages": [
5+
{
6+
"id": "Microsoft.AspNetCore.SignalR.Protocols.MessagePack",
7+
"affected": "1.0.0",
8+
"fix": "1.0.11"
9+
},
10+
{
11+
"id": "Microsoft.AspNetCore.SignalR.Protocols.MessagePack",
12+
"affected": "1.0.1",
13+
"fix": "1.0.11"
14+
},
15+
{
16+
"id": "Microsoft.AspNetCore.SignalR.Protocols.MessagePack",
17+
"affected": "1.0.2",
18+
"fix": "1.0.11"
19+
},
20+
{
21+
"id": "Microsoft.AspNetCore.SignalR.Protocols.MessagePack",
22+
"affected": "1.0.3",
23+
"fix": "1.0.11"
24+
},
25+
{
26+
"id": "Microsoft.AspNetCore.SignalR.Protocols.MessagePack",
27+
"affected": "1.0.4",
28+
"fix": "1.0.11"
29+
},
30+
31+
{
32+
"id": "Microsoft.AspNetCore.SignalR.Protocols.MessagePack",
33+
"affected": "1.1.0",
34+
"fix": "1.1.5"
35+
}
36+
]
37+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"advisory_id": "RetireNet-1",
4+
"aliases": [
5+
"CVE-2019-0982"
6+
],
7+
"summary": "Microsoft Security Advisory CVE-2019-0982: ASP.NET Core Denial of Service Vulnerability",
8+
"affected_packages": [],
9+
"references_v2": [
10+
{
11+
"reference_id": "",
12+
"reference_type": "",
13+
"url": "https://github.com/aspnet/Announcements/issues/359"
14+
}
15+
],
16+
"patches": [],
17+
"severities": [],
18+
"date_published": null,
19+
"weaknesses": [],
20+
"url": "https://github.com/RetireNet/Packages/blob/master/1.json"
21+
}
22+
]

0 commit comments

Comments
 (0)