Skip to main content

SUP-COMPROMISE-001 Hijacked publish

A direct or transitive dependency matches a curated supply-chain incident in the hijacked_publish kind. The publishing credential for a legitimate maintainer was compromised, and the attacker pushed a malicious version to the registry under the legitimate package name. The package itself is fine; a specific version range is poisoned.

Catalogued incidents under this kind include:

  • INCIDENT-2018-event-stream (npm: [email protected], 3.3.7), the flatmap-stream payload targeting Copay BTC wallets.
  • INCIDENT-2021-ua-parser-js (npm: [email protected], 0.8.0, 1.0.0), the crypto-miner and credential stealer that prompted the CISA alert.
  • INCIDENT-2018-eslint-scope (npm: [email protected]), exfiltrated npm tokens from CI.
  • INCIDENT-2021-coa and INCIDENT-2021-rc (npm), the November 2021 maintainer-credential-reuse cluster.
  • INCIDENT-2024-lottie-player (npm: @lottiefiles/[email protected]), the Web3 drainer.
  • INCIDENT-2024-solana-web3-js (npm: @solana/[email protected], 1.95.7), the private-key exfiltrator.

What Vulkro detects

The detector walks every (ecosystem, name, version) triple discovered by the SCA pipeline (lockfiles and manifests across npm / PyPI / Cargo / Go / system packages) and looks each one up against the curated catalog at tools/cve-bundler/data/compromised-releases.json. A row whose kind is hijacked_publish and whose versions[] contains the installed version produces a SUP-COMPROMISE-001 finding.

Severity: the catalog row's severity field. Maps to engine severity directly (Critical, High, Medium, Low).

Confidence: High. Evidence signal: compromised-release-exact-version-match, weight 1.0, source Pattern. The match is an exact-string invariant against a hand-curated catalog, so the rubric awards full weight.

Manifest-only entries (no resolved version) are skipped: an exact-version catalog cannot match a range or an unresolved spec.

Non-compliant lockfile

{
"name": "my-app",
"version": "1.0.0",
"lockfileVersion": 3,
"packages": {
"node_modules/event-stream": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.6.tgz"
}
}
}

[email protected] matches INCIDENT-2018-event-stream.

Compliant lockfile

{
"name": "my-app",
"version": "1.0.0",
"lockfileVersion": 3,
"packages": {
"node_modules/event-stream": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz"
}
}
}

Any version outside the catalogued range is fine.

Remediation

  1. Upgrade to a known-clean version published after the incident, or downgrade to the last clean version before the compromise window. The advisory URL in the finding points at the precise affected range.
  2. Audit your machine and CI for any build artefacts produced while the compromised version was in your dependency tree. Tokens stored on developer machines or in CI runners may have been in scope of the malicious payload.
  3. Rotate every credential the host environments could have seen during the affected window: registry publish tokens, cloud provider keys, source-control tokens, anything stored in environment variables a build script could read.
  4. Run vulkro respond against every project on the machine to find every other place the same (name, version) is in use.

See also

References