How to check a manifest or lockfile against OSV

Load a manifest or lockfile and press Scan dependencies: the package names, versions and ecosystems that could be read are queried at the OSV API, and the table lists the advisories that come back with their severity and fixed version. The parsing happens in the page; only package names, versions and ecosystems are sent.

Measured here: a package.json with eight dependencies returned 13 findings, requirements.txt returned 107 findings for five packages, and a manifest naming express 5.1.0, minimist 1.2.8 and chalk 5.3.0 returned none.

  1. Drop a manifest or lockfile, or paste its text: package.json, package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, pom.xml, a CycloneDX bom.json, or lines like "npm lodash 4.17.15".
  2. Press Scan dependencies. The status line reports progress while the versions are queried at the OSV API.
  3. Read the metrics: packages checked, findings returned, and the ecosystems that were queried.
  4. Read the note under the metrics when one appears: how many ranges were checked at their lowest declared version, how many entries named no version, and whether the 100-package cap left entries out.
  5. Press Clear before the next file. It empties the text box, the table and the metrics.

Which files are read, what is queried, and what an empty result means

Which files are read

For npm: package.json (dependencies and devDependencies) and the three lockfile formats package-lock v1/v2/v3, yarn.lock and pnpm-lock.yaml. For PyPI: requirements.txt. For Maven: pom.xml, intervals included. A CycloneDX bom.json covers npm, PyPI, Maven, NuGet, Go and crates.io. Plain lines such as "npm lodash 4.17.15" are read too. A lockfile is the better input, because it carries the version actually installed rather than the constraint.

Input the reader cannot use answers with one sentence instead of a traceback: a plain text file, malformed JSON and lines joined with @ all showed "No versioned dependencies were found" and left the table empty.

What is queried

Ranges are queried at their lowest declared version: Django>=2.2,<3.0 as 2.2, and the Maven interval [4.3.0,4.3.30] as 4.3.0. The Version column shows the manifest text (">=2.2", "[4.3.0,4.3.30]") rather than the queried value, so the row can be read next to the source file.

Entries that name no registry version are left out and counted in the note: git URLs with a tag, file:, workspace:*, latest, *, ${property} references from a pom and a CycloneDX component without a purl. At most 100 packages are queried; a manifest of 120 entries sent exactly 100 queries and said so under the metrics.

What the results mean

Each row is one advisory: package, the version that was checked, the advisory id and summary, severity, and the fixed version. Details used to be fetched for 40 advisories only, which left later rows at Severity Unknown and Fixed in —; they are fetched for all of them now, and an 83-advisory manifest returned 83 rows, each with a severity and with the fixed version OSV lists for that package.

No findings does not mean the package is safe: an advisory published after this scan will not appear, and a range checked at its lowest version leaves the rest of the range unverified. If the OSV API cannot be reached, the page says so instead of showing a clean result; an HTTP 503 is reported as such. Advisory requests are made six at a time with a 20-second limit each, so a connection that stalls cannot leave the scan spinning: the affected rows come back at Severity Unknown instead.

Recent tools: