|
21 | 21 | # VulnerableCode is a free software code scanning tool from nexB Inc. and others. |
22 | 22 | # Visit https://github.com/nexB/vulnerablecode/ for support and download. |
23 | 23 |
|
24 | | -import logging |
25 | | -import re |
| 24 | +import json |
26 | 25 | from urllib.request import urlopen |
27 | 26 |
|
28 | | -import bs4 |
29 | 27 |
|
| 28 | +DEBIAN_TRACKER_URL = 'https://security-tracker.debian.org/tracker/data/json' |
30 | 29 |
|
31 | | -DEBIAN_ROOT_URL = 'https://security-tracker.debian.org' |
32 | 30 |
|
33 | | - |
34 | | -def extract_tracker_paths(html): |
35 | | - """ |
36 | | - Return a list of tracker URL paths extracted from the given `html` input. |
| 31 | +def json_data(url=DEBIAN_TRACKER_URL): |
37 | 32 | """ |
38 | | - soup = bs4.BeautifulSoup(html, 'lxml') |
39 | | - tracker_links = soup.findAll('a', href=re.compile('^/track+.*')) |
40 | | - return [link.get('href') for link in tracker_links] |
41 | | - |
42 | | - |
43 | | -def extract_cves_from_tracker(html): |
| 33 | + Return Debian vulnerabilities data fetched from `url`. |
44 | 34 | """ |
45 | | - Return all CVEs extracted from the given `html` input. |
46 | | - """ |
47 | | - cve_id = [] |
48 | | - package_name = [] |
49 | | - vulnerability_status = [] |
50 | | - soup = bs4.BeautifulSoup(html, 'lxml') |
51 | | - |
52 | | - for tag in soup.find_all('a'): |
53 | | - href = tag.get('href') |
54 | | - |
55 | | - if re.search('/tracker/CVE-(.+)', href): |
56 | | - id = re.findall('(?<=/tracker/).*', href) |
57 | | - cve_id.append(id[0]) |
| 35 | + debian_data = urlopen(url).read() |
| 36 | + return json.loads(debian_data) |
58 | 37 |
|
59 | | - if re.search('^/tracker/TEMP-+.*', href): |
60 | | - id = re.findall('(?<=/tracker/).*', href) |
61 | | - cve_id.append(id[0]) |
62 | 38 |
|
63 | | - if re.search('/tracker/source-package/(.+)', href): |
64 | | - pkg = re.findall('(?<=/tracker/source-package/).*', href) |
65 | | - package_name.append(pkg[0]) |
66 | | - |
67 | | - # if package name is empty, use the previous package name |
68 | | - if href == '/tracker/source-package/': |
69 | | - package_name.append(pkg) |
70 | | - |
71 | | - for tag in soup.find_all('td'): |
72 | | - if 'medium' in tag or 'low' in tag or 'not yet assigned' in tag: |
73 | | - vulnerability_status.append(tag.text) |
74 | | - elif tag.find_all('span', {'class': 'red'}) and tag.text == 'high**' or tag.text == 'high': |
75 | | - vulnerability_status.append(tag.text) |
76 | | - |
77 | | - return cve_id, package_name, vulnerability_status |
78 | | - |
79 | | - |
80 | | -def scrape_cves(): |
| 39 | +def extract_data(debian_data, base_release='jessie'): |
81 | 40 | """ |
82 | | - Runs the full scraping process of Debian CVEs. |
| 41 | + Return a sequence of mappings for each existing combination of |
| 42 | + package and vulnerability from a mapping of Debian vulnerabilities |
| 43 | + data. |
83 | 44 | """ |
84 | | - tracker_root_html = urlopen(f'{DEBIAN_ROOT_URL}/tracker/').read() |
85 | | - tracker_paths = extract_tracker_paths(tracker_root_html) |
86 | | - |
87 | | - cves = [] |
88 | | - for tracker_path in tracker_paths: |
89 | | - tracker_url = f'{DEBIAN_ROOT_URL}{tracker_path}/' |
90 | | - logging.info(f'Visiting: {tracker_url}') |
91 | | - html = urlopen(tracker_url).read() |
92 | | - cves.append(extract_cves_from_tracker(html)) |
93 | | - |
94 | | - return cves |
| 45 | + package_vulns = [] |
| 46 | + |
| 47 | + for package_name, vulnerabilities in debian_data.items(): |
| 48 | + if not vulnerabilities or not package_name: |
| 49 | + continue |
| 50 | + |
| 51 | + for vulnerability, details in vulnerabilities.items(): |
| 52 | + releases = details.get('releases') |
| 53 | + if not releases: |
| 54 | + continue |
| 55 | + |
| 56 | + release = releases.get(base_release) |
| 57 | + if not release: |
| 58 | + continue |
| 59 | + |
| 60 | + package_vulns.append({ |
| 61 | + 'package_name': package_name, |
| 62 | + 'vulnerability_id': vulnerability, |
| 63 | + 'status': release.get('status'), |
| 64 | + 'urgency': release.get('urgency'), |
| 65 | + 'fixed_version': release.get('fixed_version') |
| 66 | + }) |
| 67 | + return package_vulns |
0 commit comments