The recent axios supply chain attack exposed a gap in NodeSecure's detection capabilities. The malicious package plain-crypto-js@4.2.1 — a doppelganger of the legitimate crypto-js — was injected as a phantom dependency into axios@1.14.1 and axios@0.30.4, dropped a cross-platform RAT via a postinstall script, and self-destructed after execution. NodeSecure failed to flag this package as suspicious.
This issue proposes a new Package Integrity Security Layer to detect such attacks proactively.
Background
The attack leveraged several techniques that should be detectable:
- Phantom dependency injection:
plain-crypto-js appeared in package.json but was never imported anywhere in the axios source code.
postinstall script as dropper: the entire malicious payload was triggered via a postinstall hook in an injected dependency.
- Doppelganger package:
plain-crypto-js cloned the name, description, author, and repository URL of the legitimate crypto-js package, differing only in the name field and the added postinstall script.
- Version spoofing: after execution,
package.json was replaced with a clean stub reporting a different version (4.2.0) to evade post-infection audits.
- Trusted Publisher bypass: the malicious axios versions were published manually via a stolen token, breaking the established OIDC Trusted Publisher pattern used by all legitimate releases.
Proposed Detection Layer
Trigger Conditions
A package should be flagged for deeper inspection when one or more of the following conditions are met:
Validation Steps (when a package is flagged)
Once a package is flagged, the following checks should be performed:
-
Remote package.json name verification
Fetch the package.json from the declared GitHub repository (via the repository field) and assert that the name field matches the npm package name. A mismatch (e.g. npm name plain-crypto-js pointing to the brix/crypto-js repo) is a strong signal of a doppelganger.
-
Downgrade / version integrity policy
Cross-reference the installed version against the previous versions of the package on the registry. Verify:
- Whether the publish method changed (e.g. OIDC Trusted Publisher → manual token)
- Whether the
gitHead field is absent (no corresponding Git commit/tag)
- Whether the
postinstall script is new relative to the previous version (regression check)
- Optionally: check npm attestations/provenance for the package
Expected Outcome
When this layer detects a flagged package, NodeSecure should:
- Emit a warning or error identifying the specific trigger condition(s)
- Report the result of the remote name verification
- Report any version integrity anomalies
The recent axios supply chain attack exposed a gap in NodeSecure's detection capabilities. The malicious package
plain-crypto-js@4.2.1— a doppelganger of the legitimatecrypto-js— was injected as a phantom dependency intoaxios@1.14.1andaxios@0.30.4, dropped a cross-platform RAT via apostinstallscript, and self-destructed after execution. NodeSecure failed to flag this package as suspicious.This issue proposes a new Package Integrity Security Layer to detect such attacks proactively.
Background
The attack leveraged several techniques that should be detectable:
plain-crypto-jsappeared inpackage.jsonbut was never imported anywhere in the axios source code.postinstallscript as dropper: the entire malicious payload was triggered via apostinstallhook in an injected dependency.plain-crypto-jscloned the name, description, author, and repository URL of the legitimatecrypto-jspackage, differing only in thenamefield and the addedpostinstallscript.package.jsonwas replaced with a clean stub reporting a different version (4.2.0) to evade post-infection audits.Proposed Detection Layer
Trigger Conditions
A package should be flagged for deeper inspection when one or more of the following conditions are met:
postinstall(or other lifecycle) script is present inpackage.jsondependenciesbut has zerorequire()/importusages in the source treeValidation Steps (when a package is flagged)
Once a package is flagged, the following checks should be performed:
Remote
package.jsonname verificationFetch the
package.jsonfrom the declared GitHub repository (via therepositoryfield) and assert that thenamefield matches the npm package name. A mismatch (e.g. npm nameplain-crypto-jspointing to thebrix/crypto-jsrepo) is a strong signal of a doppelganger.Downgrade / version integrity policy
Cross-reference the installed version against the previous versions of the package on the registry. Verify:
gitHeadfield is absent (no corresponding Git commit/tag)postinstallscript is new relative to the previous version (regression check)Expected Outcome
When this layer detects a flagged package, NodeSecure should: