LabRoundupColumnNews
blog/Articles/OSS Supply Chain Scanner — paste package.json, requirements.txt, pyproject.toml
oss-supply-chain-scanner-cover-en

OSS Supply Chain Scanner — paste package.json, requirements.txt, pyproject.toml

Paste a package.json, requirements.txt, or pyproject.toml and instantly check your dependencies against OSV.dev's vulnerability database. Free, browser-only, no signup. Supports npm, pip, Poetry, uv, and Rye. Built as a hub for our axios, LiteLLM, Trivy, and GlassWorm supply chain coverage.

Lab Updated today
avatar-m-1

Makoto Horikawa

Backend Engineer / AWS / Django

2026.05.276 min0 views
Key takeaways

Paste a package.json, requirements.txt, or pyproject.toml and instantly check your dependencies against OSV.dev's vulnerability database. Free, browser-only, no signup. Supports npm, pip, Poetry, uv, and Rye. Built as a hub for our axios, LiteLLM, Trivy, and GlassWorm supply chain coverage.

Paste your dependencies, get the answer in 10 seconds. A free, browser-only scanner.

Paste a package.json, requirements.txt, or pyproject.toml, hit Scan, and the tool tells you whether any of your declared dependencies has a known vulnerability. No signup, no install, just the browser.

The motivation comes from the past six months: axios (1 billion weekly downloads) compromised, LiteLLM hijacked, Trivy triggering a cascade that took down four OSS in ten days, GlassWorm hiding malware in invisible characters. OSS supply chain attacks are now routine. I wanted a 10-second answer to "is my project actually OK?" without firing up a CLI.

Try pasting your file in the textarea below. The three sample buttons load an npm, pip, or Poetry example.

OSS Supply Chain Scanner

Examples:

Data source: OSV.dev (Google, CC BY 4.0). The query runs entirely in your browser; pasted content is sent only to OSV.dev.

Quick glossary — what CVE, OSV, and "dependencies" actually mean

If you ran the scanner and the results came back full of CVE, GHSA, and OSV labels, or you are not sure what a package.json "dependency" even is, here is the one-level-down explanation for the terms in this article. Engineers with a vulnerability scanner already in CI can skip this section.

TermIn one sentenceA level deeper
dependencyA piece of someone else's code
your project borrows to run
A typical web app pulls in dozens to thousands
of libraries. This tool inspects only the ones
you borrow directly.
package.jsonThe dependency list
for Node.js / npm projects
A JSON file declaring "this project uses
this library at this version range".
requirements.txtThe dependency list
for Python / pip projects
The file pip install -r requirements.txt
reads to install everything at once.
pyproject.tomlThe modern dependency list
for Python (Poetry / uv / Rye)
The successor to requirements.txt,
following the PEP 621 standard.
Describes the whole project in one file.
CVEThe global tracking number
for a security flaw
Common Vulnerabilities and Exposures.
Format: CVE-2026-8832.
Coordinated by MITRE in the US.
GHSAGitHub's own
security advisory ID
GitHub Security Advisory.
Format: GHSA-xxxx-xxxx-xxxx.
Tightly coupled to npm / PyPI; sometimes
published before a CVE number is assigned.
OSVA federated database
of vulnerability records
Open Source Vulnerability.
Hosted by Google, aggregates GitHub,
PyPA, Rust Foundation, and more.
This is the database the scanner queries.
SemVerThe global convention
for version numbers
Semantic Versioning.
1.2.3 = major.minor.patch.
^1.2.3 means "latest 1.x".
supply chain
attack
A library you trust
gets quietly poisoned
Attacker publishes a malicious version
of a library with millions of downloads.
Every project that pulls the update
is infected at once.

Read end-to-end, the scanner does this: read the list of libraries your project borrows (package.json and friends), and check each one against the global wound register (OSV) keyed by the security flaw IDs (CVE / GHSA). A supply chain attack is when one of those borrowed libraries itself gets poisoned — imagine the locksmith who cut your house key being bought off.

If your team already runs npm audit or Trivy in CI, this exact lookup is happening behind the scenes on every build. This tool is just that same lookup, manually, in your browser, once.

Why browser-only?

Tools that do this already exist: npm audit, pip-audit, Trivy, Snyk, Dependabot. If you are a professional engineer, you have probably wired one of them into CI.

But the real-world friction shows up elsewhere:

  • · A vendor sends you a package.json and you want a sanity check before the PR review
  • · An OSS supply chain attack hits the news and your Slack lights up with "are we affected?"
  • · You spot an interesting GitHub repo and want a dependency health check before cloning
  • · You need to audit code written by a non-engineer manager or a freelance contractor

In all of these, installing a tool locally is too much friction, corporate proxies block CLIs, or you simply lack permission. Paste-and-click takes 10 seconds.

The other reason is that I wanted a landing point for the individual incident articles on this site. axios, LiteLLM, Trivy, GlassWorm, TeamPCP—each post tells the story of an attack, but until now there was no "and here is how you check yours" exit. This tool is that exit.

How it works under the hood

There is no backend. The page is HTML and JavaScript; whatever you paste is sent straight to the OSV.dev public API and the result is rendered in the browser. OSV.dev is a vulnerability database operated by Google, aggregating GitHub Security Advisory, PyPA, the Rust Foundation, and other upstream sources. It is unauthenticated, CORS-enabled, and accepts up to 1,000 packages per batch.

The pipeline is four steps:

StepWhat happensLibrary used
(1) Format detectionStarts with { → npm. Contains [project] → Poetry/
PEP 621. Otherwise requirements.txt.
Hand-rolled heuristic
(2) Dep extractionJSON.parse / TOML parse /
regex per line
smol-toml
(3) Version normalizationResolve ^1.7.7 or >=2.0.0,<3
to the lowest compatible version
semver
(4) Vulnerability matchPOST all deps to OSV.dev
/v1/querybatch in one request
fetch API

Step (3) was the messiest. OSV.dev does not accept SemVer ranges like ^1.7.7, so we collapse a range to its lowest compatible version using semver.minVersion() and query that. It is the safer side to err on.

So "axios": "^1.7.7" is queried as 1.7.7 even if your install resolves to 1.7.9 or 1.8.2. Without lock files we cannot do better, and accepting that tradeoff is what keeps the tool useful for declaration-only files.

The match itself looks like this (the full source is in the page HTML):

// Ship every dep to OSV.dev in a single batch
const queries = deps.map(d => ({
  package: { name: d.name, ecosystem: d.ecosystem }, // npm / PyPI
  version: d.resolvedVersion,                         // normalized via semver.minVersion()
}));

const res = await fetch("https://api.osv.dev/v1/querybatch", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ queries }),
});
const { results } = await res.json();
// results[i] is the vuln list for deps[i].

No backend means there is nothing for me to operate, but more importantly your package.json, even one from a proprietary internal project, never touches my servers. OSV.dev is the only third party in the loop, and they are transparent about what they store.

The fine print on each input format

package.json (npm / yarn / pnpm)

All four dependency fields are picked up: dependencies, devDependencies, optionalDependencies, peerDependencies. Excluded: workspaces (local refs), npm: aliases, and VCS specs like git+ssh://.

requirements.txt (pip / pip-tools / pipenv-lock exports)

Supports the operators ==, >=, ~=, !=. Comma-separated specs on a single line (django>=4.0,<5.0) collapse to the lowest version. Lines starting with -r, -e, or --index-url, plus # comments, are skipped.

pyproject.toml (Poetry / uv / Rye / PEP 621)

Two competing styles coexist in the wild; both are supported:

  • PEP 621 standard (uv, Rye, Hatch, etc.): the array [project].dependencies and the table [project.optional-dependencies]. Each entry is a PEP 508 string like "requests>=2.28.0".
  • Poetry style: the table [tool.poetry.dependencies] and grouped [tool.poetry.group.*.dependencies]. Values are SemVer-flavored strings ("^2.28.0") or inline tables like { version = "...", extras = [...] }.

Parsing is done with the lightweight smol-toml library. The python entry and any inline tables with path, git, or url (local or VCS refs) are excluded from the OSV query.

What this tool does not catch

Worth listing the blind spots so the tool is not over-trusted:

  • ? Transitive dependencies are invisible. Only the top-level deps you declared are scanned. A lock file (package-lock.json, poetry.lock) would cover them, but this tool intentionally targets the small declaration files.
  • ? Range-only specs are scored at their lowest version. Your actually-installed version may be newer and unaffected, or older and worse off. Treat this as a coarse health check, not a 0-day verdict.
  • ? Unpublished vulnerabilities won't appear. There is always a window between disclosure and OSV.dev indexing.
  • ? Pure malware injection isn't detected. If a compromised package was assigned a CVE or GHSA, it shows up; if it wasn't (the first 24 hours of most supply chain attacks), nothing here will help. GlassWorm-style invisible-character malware is also out of scope.

For real coverage you need npm audit or Trivy in CI, SBOM discipline, and committed lock files. This tool is the "paste-and-glance" rung below that.

Recent OSS supply chain attacks (2025–2026)

Below is a timeline of the supply chain incidents covered on this site over the past several months. Each row links to the full write-up with the detection details and blast radius at the time.

WhenIncidentScopeArticle
2026-05axios npm hijack1B weekly downloads
RAT planted in package
axios article
2026-04Trivy cascade4 OSS fell in 10 days
the defender's tool itself broken
cascade / Trivy 3rd time
2026-04Telnyx PyPI breachMalware hidden
inside a WAV file
Telnyx
2025-12LiteLLM hijack95M monthly downloads
Python startup = pwn
LiteLLM / .pth trace
2025-10GlassWormMalware hidden in
invisible Unicode chars
GlassWorm

The technique changes every time, but the entry point is the same: "a package you trust bumps a version, and somewhere in there a stranger has rewritten the contents." Routinely glancing at the dependency file you never touch is, in effect, a defense line.

Roadmap and requests

Current scope stops at "paste three formats." Planned for the next pass:

  • package-lock.json and poetry.lock support (transitive deps included)
  • Gemfile / Cargo.toml / go.mod
  • Direct GitHub URL scanning (needs an API proxy for CORS)

If something is missing for your workflow, drop a comment or use the contact form and the priority list gets reshuffled.

Sources and licensing

OSV.dev vulnerability metadata is redistributed under CC BY 4.0. This tool is an independent client and is not an OSV.dev or Google product.