@@ -49,6 +49,8 @@ assert shutil.which("osv-scanner"), "missing osv-scanner"
4949
5050def _audit_formula (formula , requirements ):
5151 # osv-scanner wants a requirements.txt file, so we make a temporary one.
52+ # These are pinned formula resources, including packaged transitive dependencies.
53+ # Resolving additional dependencies would scan packages outside that inventory.
5254 with NamedTemporaryFile (mode = "w" ) as req_file :
5355 req_file .write ("\n " .join (requirements ))
5456 req_file .flush ()
@@ -58,6 +60,7 @@ def _audit_formula(formula, requirements):
5860 "osv-scanner" ,
5961 "--lockfile" ,
6062 f"requirements.txt:{ req_file .name } " ,
63+ "--no-resolve" ,
6164 "--format=json" ,
6265 "--config=osv-scanner-config.toml" ,
6366 ],
@@ -78,10 +81,14 @@ with concurrent.futures.ThreadPoolExecutor(max_workers=_JOBS) as pool:
7881 formula , result = fut .result ()
7982 prefix = f"[{ n_complete :>{width }} /{ n_total } ]"
8083
81- # If we don't see anything on stdout, osv-scanner probably failed.
82- # Log it as an error.
83- if not result .stdout :
84- print (f"\t { prefix } >:( osv-scanner failed: { result .stderr } " , file = sys .stderr )
84+ # osv-scanner exits 0 for a clean scan and 1 when it finds vulnerabilities.
85+ # Other exits or missing output mean we do not have a complete scan.
86+ if result .returncode not in (0 , 1 ) or not result .stdout :
87+ print (
88+ f"\t { prefix } >:( osv-scanner failed for { formula } "
89+ f"(exit { result .returncode } ): { result .stderr } " ,
90+ file = sys .stderr ,
91+ )
8592 audits ["failures" ].append (formula )
8693 continue
8794
@@ -123,6 +130,15 @@ for (dep, vuln), formulas in sorted(_SUMMARY_RESULTS.items()):
123130 formulas_rendered = ", " .join (f"`{ f } `" for f in formulas )
124131 render += f"| `{ dep } ` | [`{ vuln } `](https://osv.dev/vulnerability/{ vuln } ) | { formulas_rendered } |\n "
125132
133+ if audits ["failures" ]:
134+ failures_rendered = "\n " .join (f"- `{ f } `" for f in sorted (audits ["failures" ]))
135+ failure_message = f"Audit incomplete: failed to scan { len (audits ['failures' ])} of { n_total } formulae."
136+ render = f"## Audit incomplete\n \n { failure_message } \n \n { failures_rendered } \n \n { render } "
137+
126138if _SUMMARY :
127139 with _SUMMARY .open (mode = "a" ) as io :
128140 print (render , file = io )
141+
142+ if audits ["failures" ]:
143+ print (failure_message , file = sys .stderr )
144+ sys .exit (1 )
0 commit comments