Supply Chain

OpenSSF Malicious Packages: The Feed Your SCA Scanner Needs

April 20, 2026 8 min read SCA · Supply Chain

Software Composition Analysis used to be about one thing: cross-reference every dependency in your manifest with the CVE/NVD database, then warn on anything with a published vulnerability. That model still works — but it misses a category of attack that has become the dominant supply-chain threat: packages that are not vulnerable because they are intentionally malicious from the first line.

This post explains why generic SCA misses these attacks, what the OpenSSF Malicious Packages dataset actually is, and how to wire it into any SCA workflow using the OSV.dev API.

The inflection point: SonarQube 2026.1 added malicious-package detection as a headline feature. Snyk, Socket and GitHub Advanced Security have been shipping it for years. If your SCA scanner still only reports CVEs, it is missing the supply-chain attacks that actually made the news this decade.

Why CVE-only SCA is not enough

Traditional SCA assumes a package is trustworthy until proven vulnerable. That made sense when the only way a dependency could hurt you was a bug. But four attack patterns have since arrived that all share the same property — the package is malicious by design, not by accident:

None of these show up in the CVE database, because CVEs describe bugs in otherwise-legitimate code.

What OpenSSF Malicious Packages is

The Open Source Security Foundation maintains a dataset called malicious-packages — a curated, public, community-contributed list of packages that have been confirmed malicious. It is published in OSV schema JSON, organized by ecosystem:

malicious/
+-- npm/
+-- pypi/
+-- maven/
+-- nuget/
+-- rubygems/
+-- crates.io/
+-- go/
+-- ...

Every entry carries a MAL-YYYY-NNNN identifier, a summary, the affected package and version range, and references to the investigation. OpenSSF does the curation; publishers (GitHub Security Lab, Sonatype, Checkmarx, Phylum, researchers) contribute reports.

How OSV.dev makes it queryable

OSV.dev is Google's unified vulnerability API that aggregates OpenSSF Malicious Packages alongside GHSA, PyPA, RustSec and many others. Two endpoints matter for SCA integration:

A minimal query:

curl -s -X POST https://api.osv.dev/v1/query \
  -H 'Content-Type: application/json' \
  -d '{
    "package": { "name": "ua-parser-js", "ecosystem": "npm" },
    "version": "0.7.29"
  }'

The response returns an array of vulnerabilities. Anything with an id starting with MAL- is a malicious-package finding — distinct from a regular CVE.

Four incidents every engineer should know

event-stream + flatmap-stream (2018)

A maintainer handed over control of a widely-depended-on npm package to an attacker. The attacker injected a crypto-wallet stealer via a sub-dependency. Downloaded eight million times before detection.

ua-parser-js, coa, rc (2021)

Three widely-used npm packages taken over through maintainer account compromise in the same campaign. Released tainted versions containing credential stealers and crypto miners.

PyPI ctx & phpass (May 2022)

Attackers seized abandoned PyPI accounts and published malicious drop-in replacements that exfiltrated AWS credentials on import. Both packages had active download traffic.

colors.js / faker.js / node-ipc (2022)

Not a takeover — the original maintainers shipped destructive protestware themselves. node-ipc's "peacenotwar" module wrote a file to disk on every user's machine matching certain geolocations.

Every one of these was present in the OpenSSF dataset within days or hours of discovery. A scanner that queried OSV would have flagged them; a pure CVE scanner would not.

Integration pattern — keep a local mirror

Calling OSV.dev for every dependency in every scan is wasteful and fragile. The better pattern is a DB-backed local registry refreshed on a schedule:

  1. Seed the DB with a curated list of well-known incidents. This makes the platform useful even if the feed is unreachable.
  2. Sync daily from OSV: for each tracked package, fetch any MAL-* entries and upsert.
  3. Check during every SCA scan: for each dependency parsed from package.json, requirements.txt, *.csproj, query the local DB. Match → raise a Critical finding.
  4. Fail gracefully. If the sync can't reach OSV, log a warning and keep using the local mirror. Never let a network error break a scan.

This design means your SCA is resilient to feed outages, fast (in-memory lookups), and always current within 24 hours of a new incident being reported.

What raising a Critical finding should look like

When a match lands, give engineers everything they need to triage in the finding itself:

Title:        Malicious package detected: ua-parser-js
Severity:     Critical
Source:       SCA
Category:     Malicious Package
CWE:          CWE-506 (Embedded Malicious Code)
OWASP:        A08:2021 (Software & Data Integrity Failures)
Exploitable:  Actively Exploited
Advisory:     OSV:MAL-2022-XXXX (OpenSSF)
Reference:    https://osv.dev/vulnerability/MAL-2022-XXXX
Summary:      Maintainer account compromise Oct 2021. Tainted versions
              shipped crypto-miner and credential stealer payloads.
Remediation:  Remove 'ua-parser-js' immediately, pin a known-safe
              version (>= 1.0.40), rotate any credentials that may
              have been exposed.

Category "Malicious Package" is important — it lets dashboards and compliance reports distinguish "vulnerable dependency" (patch it) from "malicious dependency" (remove it and rotate credentials).

Beyond detection — blocking in CI

Once the registry exists and findings are surfacing, the obvious next step is to block builds. A quality gate like "fail the build if any Critical with VulnerabilityType = MaliciousPackage exists" is a one-line addition to most policy engines.

Resist the temptation to block on any malicious match without a human in the loop, at least until your detection is well-calibrated. False positives in SCA do exist (names get re-registered, advisories get rescinded). Starting with a Critical finding + Slack alert gives engineers a chance to exercise judgment; hard-blocking can follow.

Takeaway

OpenSSF Malicious Packages is the closest thing the ecosystem has to a canonical list of "packages that are out to get you." It is public, free, maintained by people you can trust, and trivially queryable via OSV.dev. There is no good reason for a 2026 SCA scanner to skip it.

See malicious-package findings in action

Security Factor 365 ships a DB-backed registry seeded with documented incidents and synced daily from OSV.dev. Every SCA scan checks it automatically.

Explore SF365