2525- retire.js
2626- npm audit
2727- yarn audit
28+ - pip-audit
2829
2930[i] Identifiers mapping:
3031
3435- retire.js => retirejs
3536- npm audit => npm-audit
3637- yarn audit => yarn-audit
38+ - pip-audit => pip-audit
3739
3840[i] Command lines to generate the data file used by this script:
3941
5658
5759yarn audit
5860=> yarn audit --json > report.json
61+
62+ pip-audit
63+ => pip-audit --requirement requirements.txt --format json --output report.json
5964"""
6065
6166ENTRY_MAX_LENGTH_FOR_DISPLAY = 30
6267DEFAULT_ENCODING = "utf-8"
6368VULN_IDS_FILE = "global-cve-ghsa.txt"
64- SCA_TOOLS_IDENTIFIERS = ["owasp-dependency-check" , "dotnet-package-list" , "osv-scanner" , "retirejs" , "npm-audit" , "yarn-audit" ]
69+ SCA_TOOLS_IDENTIFIERS = ["owasp-dependency-check" , "dotnet-package-list" , "osv-scanner" , "retirejs" , "npm-audit" , "yarn-audit" , "pip-audit" ]
6570USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
6671REQ_SESSION = requests .session ()
6772# Needed for ENISA API otherwise an HTTP 403 is received
7782# https://deps.dev/_/s/maven/p/com.thoughtworks.xstream%3Axstream/v/1.4.10
7883# https://deps.dev/_/s/nuget/p/system.text.json/v/9.0.6
7984DEPSDEV_URL_TPL = "https://deps.dev/_/s/%s/p/%s/v/%s"
85+ # KEY is the package manager official name and VALUE if the corresponding name used by deps.dev
86+ DEPSDEV_PACKAGE_MANAGER_MAPPING = {"pip" : "pypi" }
8087
8188
8289@functools .total_ordering
@@ -188,6 +195,9 @@ def find_fix_exists_for_osv_scanner_vuln(vulnerability):
188195
189196
190197def find_if_false_positive (package_name , package_version , package_manager , cves_id_list ):
198+ depdev_package_manager_name = package_manager
199+ if package_manager in DEPSDEV_PACKAGE_MANAGER_MAPPING :
200+ depdev_package_manager_name = DEPSDEV_PACKAGE_MANAGER_MAPPING [package_manager ]
191201 # When the version contain a range (it is the case for NPM) then I consider that
192202 # I cannot perform the validation against DEPS.DEV
193203 if len (re .findall (r'[\<\>|\*]+' , package_version )) > 0 or " - " in package_version :
@@ -200,7 +210,7 @@ def find_if_false_positive(package_name, package_version, package_manager, cves_
200210 try :
201211 package_name_adapted = package_name .replace ("/" , ":" ) # on deps.dev the group name and the artefact name are separated by ":"
202212 package_name_adapted = encode_package_name (package_name_adapted )
203- package_depsdev_url = DEPSDEV_URL_TPL % (package_manager , package_name_adapted , package_version )
213+ package_depsdev_url = DEPSDEV_URL_TPL % (depdev_package_manager_name , package_name_adapted , package_version )
204214 response = REQ_SESSION .get (package_depsdev_url , timeout = REQ_TIMEOUT )
205215 if response .status_code == 200 :
206216 cves_id_found = []
@@ -521,6 +531,46 @@ def load_data_from_retirejs(json_data):
521531 return vulnerable_components
522532
523533
534+ def load_data_from_pip_audit (json_data ):
535+ vulnerable_components = []
536+ package_manager_name = "pip"
537+ for dep in json_data ["dependencies" ]:
538+ vulns = dep ["vulns" ]
539+ component_name = dep ["name" ]
540+ component_version = dep ["version" ]
541+ for vuln in vulns :
542+ ghsa = vuln ["id" ]
543+ cves = vuln ["aliases" ]
544+ fixed_versions = vuln ["fix_versions" ]
545+ if len (fixed_versions ) > 0 :
546+ extra = "Fixed in versions " + "," .join (fixed_versions )
547+ else :
548+ extra = ""
549+ # As the CVSS score is not provided then retrieve
550+ # the severity and the score using the CVE ID (take first CVE as the reference)
551+ cve_id = cves [0 ]
552+ data = find_cve_severity ([cve_id ])
553+ if data [cve_id ] is not None :
554+ cvss_score = data [cve_id ][0 ]
555+ severity = data [cve_id ][1 ]
556+ else :
557+ cvss_score = 0
558+ severity = "NA"
559+ vulnerable_component = VulnerableComponentProperties ()
560+ vulnerable_component .package_name = component_name
561+ vulnerable_component .version = component_version
562+ vulnerable_component .file_name = "-"
563+ vulnerable_component .ghsa_ids = ghsa
564+ vulnerable_component .cve_ids = CVE_GHSA_CWE_SEPARATOR_CHAR .join (cves )
565+ vulnerable_component .cwe_ids = ""
566+ vulnerable_component .cvss_score = cvss_score
567+ vulnerable_component .severity = severity
568+ vulnerable_component .extra_information = extra
569+ vulnerable_component .package_manager = package_manager_name
570+ vulnerable_components .append (vulnerable_component )
571+ return vulnerable_components
572+
573+
524574def enrich_with_false_positive_marker (vulnerable_components ):
525575 for vulnerable_component in vulnerable_components :
526576 cves_id_list = vulnerable_component .cve_ids .split (CVE_GHSA_CWE_SEPARATOR_CHAR )
@@ -557,6 +607,8 @@ def load_information(input_data_file, sca_tool_id):
557607 vulnerable_components = load_data_from_npm_audit (components_data )
558608 elif sca_tool_id == "yarn-audit" :
559609 vulnerable_components = load_data_from_yarn_audit (components_data )
610+ elif sca_tool_id == "pip-audit" :
611+ vulnerable_components = load_data_from_pip_audit (components_data )
560612 else :
561613 raise Exception ("SCA tools not supported!" )
562614 return vulnerable_components
0 commit comments