Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- coding: utf-8 -*-
- import click
- import pip
- import requests
- from packaging.specifiers import SpecifierSet
- from .errors import DatabaseFetchError
- from .constants import DATABASE_MIRRORS, REQUEST_TIMEOUT
- from collections import namedtuple
- class Vulnerability(namedtuple("Vulnerability", ["name", "spec", "version", "data"])):
- @property
- def source(self):
- return self.cve_id if self.is_cve else "changelog"
- @property
- def is_cve(self):
- return "cve" in self.data
- @property
- def is_changelog(self):
- return "changelog" in self.data
- @property
- def cve_id(self):
- return self.data["cve"]
- @property
- def description(self):
- return self.data["description"] if self.is_cve else self.data["changelog"]
- def fetch_database(full=False):
- for mirror in DATABASE_MIRRORS:
- db_name = "insecure_full.json" if full else "insecure.json"
- url = mirror + db_name
- r = requests.get(url=url, timeout=REQUEST_TIMEOUT)
- return r.json()
- raise DatabaseFetchError()
- def get_vulnerabilities(pkg, spec, db):
- for entry in db[pkg]:
- if spec == entry["v"]:
- yield entry
- def check(packages):
- db = fetch_database()
- db_full = None
- vulnerable_packages = frozenset(db.keys())
- vulnerable = []
- for pkg in packages:
- # normalize the package name, the safety-db is converting underscores to dashes and uses
- # lowercase
- name = pkg.key.replace("_", "-").lower()
- if name in vulnerable_packages:
- # we have a candidate here, build the spec set
- for specifier in db[name]:
- spec_set = SpecifierSet(specifiers=specifier)
- if spec_set.contains(pkg.version):
- if not db_full:
- db_full = fetch_database(full=True)
- for data in get_vulnerabilities(pkg=name, spec=specifier, db=db_full):
- vulnerable.append(
- Vulnerability(name=name, spec=specifier, version=pkg.version, data=data)
- )
- return vulnerable
Add Comment
Please, Sign In to add comment