Skip to content

Commit 39df9ea

Browse files
authored
Merge pull request #153 from sbs2001/develop
Add importer for Python safetydb
2 parents 193e953 + 043bc1c commit 39df9ea

3 files changed

Lines changed: 98 additions & 1 deletion

File tree

vulnerabilities/data_dump.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,38 @@ def rust_dump(extract_data):
262262
vulnerability=vulnerability,
263263
package=unaffected_package
264264
)
265+
266+
267+
def safetydb_dump(extract_data):
268+
for package_data in extract_data:
269+
vulnerability, _ = Vulnerability.objects.get_or_create(
270+
summary=package_data['description'],
271+
cve_id=package_data['cve_id']
272+
)
273+
274+
VulnerabilityReference.objects.get_or_create(
275+
vulnerability=vulnerability,
276+
reference_id=package_data['vuln_id']
277+
)
278+
279+
for version in package_data['affected_versions']:
280+
affected_package = Package.objects.create(
281+
name=package_data['package_name'],
282+
type='pypi',
283+
version=version
284+
)
285+
ImpactedPackage.objects.create(
286+
vulnerability=vulnerability,
287+
package=affected_package
288+
)
289+
290+
for version in package_data['unaffected_versions']:
291+
unaffected_package = Package.objects.create(
292+
name=package_data['package_name'],
293+
type='pypi',
294+
version=version
295+
)
296+
ResolvedPackage.objects.create(
297+
vulnerability=vulnerability,
298+
package=unaffected_package
299+
)

vulnerabilities/management/commands/import.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
from django.core.management.base import BaseCommand, CommandError
2525

2626
from vulnerabilities import data_dump as dd
27-
from vulnerabilities.scraper import debian, ubuntu, archlinux, npm, ruby, rust
27+
from vulnerabilities.scraper import debian, ubuntu, archlinux, npm, ruby, rust, safety_db
2828

2929
IMPORTERS = {
30+
'safetydb': lambda: safety_db.import_vulnerabilities(),
3031
'rust': lambda: dd.rust_dump(rust.import_vulnerabilities()),
3132
'ruby': lambda: dd.ruby_dump(ruby.import_vulnerabilities()),
3233
'npm': lambda: dd.npm_dump(npm.scrape_vulnerabilities()),
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Data Imported from https://github.com/pyupio/safety-db
2+
import json
3+
from urllib.error import HTTPError
4+
from urllib.request import urlopen
5+
from dephell_specifier import RangeSpecifier
6+
7+
URL = 'https://raw.githubusercontent.com/pyupio/safety-db/master/data/insecure_full.json'
8+
9+
10+
def get_data_file():
11+
with urlopen(URL) as file:
12+
json_file = json.load(file)
13+
return json_file
14+
15+
16+
def get_all_versions_of_package(package_name):
17+
url = "https://pypi.org/pypi/{}/json".format(package_name)
18+
releases = set()
19+
try:
20+
with urlopen(url) as response:
21+
json_file = json.load(response)
22+
except HTTPError: # PyPi does not have data about this package, we skip these
23+
return releases
24+
for release in json_file['releases']:
25+
releases.add(release)
26+
return releases
27+
28+
29+
def import_vulnerabilities():
30+
vulnerability_package_dicts = []
31+
data = get_data_file()
32+
cves = set()
33+
for package_name in data:
34+
all_package_versions = set(get_all_versions_of_package(package_name))
35+
if len(all_package_versions) == 0:
36+
# PyPi does not have data about this package, we skip these
37+
continue
38+
for advisory in data[package_name]:
39+
description = advisory['advisory']
40+
cve_id = advisory.get('cve')
41+
vuln_id = advisory['id']
42+
vuln_version_ranges = advisory['specs']
43+
for vuln_version_range in vuln_version_ranges:
44+
version_range = RangeSpecifier(vuln_version_range)
45+
affected_versions = set()
46+
for version in all_package_versions:
47+
if version in version_range:
48+
affected_versions.add(version)
49+
unaffected_versions = all_package_versions - affected_versions
50+
if cve_id not in cves:
51+
# This data has duplicates hence the check
52+
vulnerability_package_dicts.append({
53+
'package_name': package_name,
54+
'vuln_id': vuln_id,
55+
'affected_versions': affected_versions,
56+
'unaffected_versions': unaffected_versions,
57+
'cve_id': cve_id,
58+
'description': description
59+
})
60+
cves.add(cve_id)
61+
return vulnerability_package_dicts

0 commit comments

Comments
 (0)