1. Account Takeover | How jasonsaayman's npm Credentials Were Compromised
The attack began with a credential compromise of jasonsaayman, the lead maintainer of the axios GitHub repository and npm package. The attacker obtained jasonsaayman's npm login credentials, changed the account's registered email address to a ProtonMail address, and gained full publish rights to the package.
BY THE NUMBERS
83M
axios weekly npm downloads
6 min
Socket detection time
2
Malicious versions published
3
Platforms targeted (Win, Mac, Linux)
Once in control, the attacker manually published two malicious releases: axios@1.14.1 and axios@0.30.4. Both bypassed the project's standard GitHub Actions CI/CD pipeline entirely. Neither has a corresponding GitHub commit or tag, a clear deviation from the project's established release hygiene, where every legitimate 1.x release is published via npm's OIDC Trusted Publisher mechanism with a verifiable commit in the repository.
Legitimate axios Release Pattern
Published via GitHub Actions with OIDC Trusted Publisher.
Every version has a corresponding Git tag and commit in axios/axios.
Release notes published to GitHub Releases within minutes of npm publish.
Provenance attestation available via npm info axios@[version] dist.integrity.
Malicious Versions 1.14.1 and 0.30.4
Published manually from the compromised jasonsaayman account.
No Git tag, no commit, no GitHub release entry.
No OIDC provenance attestation in the npm registry.
Contained an injected dependency ΓÇö plain-crypto-js@4.2.1 ΓÇö not present in any prior version.
The choice to target axios was deliberate. With roughly 83 million weekly downloads, axios sits in the dependency trees of an enormous share of Node.js applications, CI/CD build pipelines, and serverless functions. A malicious version that goes undetected for even a few hours can propagate to tens of thousands of developers running npm install in automated pipelines.
2. The 6-Minute Detection Window | Socket Flags plain-crypto-js at 00:05:41 UTC
According to Socket's incident report, the malicious dependency plain-crypto-js@4.2.1 was published to npm at exactly 23:59:12 UTC on March 30, 2026. Socket's automated detection pipeline flagged it as malicious at 00:05:41 UTC on March 31, a response window of 6 minutes and 29 seconds.
SOCKET DETECTION REPORT
plain-crypto-js@4.2.1 as a malicious package containing an obfuscated postinstall dropper at 00:05:41 UTC, approximately six minutes after publication to the npm registry.”
StepSecurity independently confirmed the same findings. Both firms cross-analyzed the malicious versions and identified the injected dependency as the sole mechanism. Critically, the axios source code itself was not modified. The attack worked by adding a dependency to the package's package.json at publish time, meaning the malicious payload would only execute on a fresh npm install, not in any existing node_modules folder already present on a developer's machine.
Why Postinstall Scripts Are the Attack Surface
npm's postinstall script hook executes automatically when a package is installed, with the same privileges as the installing user. No confirmation, no sandbox, no permission check. Any package on npm can declare a postinstall script, and that script runs silently on every npm install. This makes postinstall the preferred infection vector for npm supply chain attacks, including the widely studied event-stream incident in 2018.
3. The Two-Layer Dropper | plain-crypto-js@4.2.1 Dissected
Rather than embedding malware directly in axios source code, the attacker decoupled the payload into a separate package, plain-crypto-js@4.2.1, which was published to npm at the same time. This staging approach is tactically significant: it allows the attacker to update or swap the payload independently and reduces the volume of suspicious code visible in the axios diff itself.
TWO-LAYER DROPPER EXECUTION CHAIN
npm install axios@1.14.1 or axios@0.30.4
Developer installs either malicious version. npm fetches the modified package.json containing plain-crypto-js@4.2.1 as a dependency.
plain-crypto-js@4.2.1 postinstall fires
npm executes the postinstall hook in plain-crypto-js automatically. No user interaction required.
Layer 1: String reversal and base64 decode
The script reverses obfuscated string constants and applies base64 decoding to reconstruct a second-stage payload in memory.
Layer 2: XOR decryption
The reconstructed payload is XOR-decrypted using a hardcoded key to produce a live executable command sequence.
C2 beacon to sfrclak.com:8000
The decrypted code contacts the command-and-control server at sfrclak.com:8000 and requests platform-specific payloads.
Platform RAT download and execution
The server delivers a remote access trojan binary matched to the detected OS: macOS, Windows (x64), or Linux (x64).
Evidence scrubbing
The dropper deletes itself and removes its entry from the installed package.json, leaving no trace in node_modules.
Obfuscation Layers in Detail
The dropper's first layer used reversed string constants, a technique that trivially evades pattern-matching scanners looking for known malicious strings. After reversal, a base64-encoded blob was decoded to produce the second layer. That second layer was then XOR-decrypted with a key embedded in the first layer, yielding fully executable JavaScript. The result was a minimal but functional stager: detect OS, contact C2, download payload, execute, clean up.
TECHNICAL NOTE
4. RAT Payloads | Separate Binaries for Windows, macOS, and Linux
The C2 server at sfrclak.com:8000 served three distinct payloads, one per platform. Cross-platform targeting at this level of specificity indicates operational maturity. A generic supply chain attack might target only a single platform or use a platform-agnostic interpreted payload. Providing OS-matched binaries requires more infrastructure investment and signals the attacker expected to infect machines across polyglot development environments, including full-stack developers on macOS running Linux servers and Windows CI agents.
Windows
x64 native executable delivered via C2 response.
Standard persistence mechanisms expected: registry run key or scheduled task.
RAT class malware provides remote shell, file access, keylogging, and screenshot capture capabilities.
macOS
Mach-O binary delivered for macOS targets.
Execution on macOS may require user to bypass Gatekeeper on first run, though Node.js child_process.exec invocations can often circumvent this.
Apple Silicon vs x64 binary architecture unconfirmed at publishing time.
Linux
ELF binary for Linux x64 environments.
Highest risk in CI/CD contexts: Linux is the dominant runner OS on GitHub Actions, GitLab CI, and Jenkins.
An infected CI runner can leak build secrets, signing keys, and deploy credentials.
The choice to offer Linux-specific payloads is the tell. These attackers were not targeting end-user developer laptops. They wanted CI/CD runners, where a single infection yields deploy keys and cloud credentials.
5. CI/CD Bypass | No GitHub Tag, No Commit, No OIDC Attestation
The absence of a corresponding GitHub tag or commit for either malicious version is the clearest signal that something was wrong, and the one that developers with proper tooling could catch immediately. Legitimate axios releases follow a strict pattern: a version bump commit, a v1.x.x tag, a GitHub Actions workflow run, and a resulting npm publish with OIDC provenance attestation attached.
None of those artifacts exist for versions 1.14.1 or 0.30.4. A developer running npm info axios@1.14.1 would see no provenance block. A developer checking the axios GitHub repository would find no release entry, no tag, and no pull request associated with those version numbers.
How to Check for Provenance Attestation
Run npm info [package]@[version] and look for a dist.attestations field. A legitimate release via Trusted Publisher includes a signed SLSA provenance statement linking the npm artifact to the exact GitHub Actions workflow run that produced it. If dist.attestations is absent or empty, the release was not published through an automated CI/CD pipeline.
For engineering teams using dependency pinning, lockfiles (package-lock.json, yarn.lock), and provenance verification in CI, this attack would have had no effect. The threat was concentrated among developers running unguarded npm install commands against floating version ranges such as ^1.14.0, which would have resolved to 1.14.1.
6. What Developers Should Do Now | Audit, Lock, and Rotate
Both malicious versions have been unpublished from the npm registry. However, developers who ran npm install during the window between 23:59:12 UTC on March 30 and roughly 01:00 UTC on March 31 may have received poisoned packages. The dropper's self-deletion makes post-hoc detection difficult.
SECURITY POSTURE INDICATORS
Audit installed axios version
Run `npm list axios` or `cat package-lock.json | grep axios` to confirm which version is in your node_modules. Versions 1.14.1 and 0.30.4 are malicious.
Rotate all secrets accessible during the install window
If you ran npm install between March 30 23:59 UTC and March 31 01:00 UTC, treat all secrets on that machine as compromised: API keys, deploy tokens, cloud credentials, signing keys.
Check CI/CD runner logs
Review GitHub Actions, GitLab CI, or Jenkins logs for any runs during the window that installed axios. Unusual outbound connections to sfrclak.com:8000 confirm infection.
Pin exact versions in package.json
Replace version ranges like `^1.14.0` with exact pins like `1.7.9` (the last clean release). Rebuild your lockfile from a clean checkout after updating.
Enable provenance verification in your CI pipeline
Add `npm install --prefer-dedupe` with `--provenance` checks, or use a tool like socket.dev's GitHub Action to block packages that lack OIDC attestation.
Sources & References
- [1] Aikido Security ΓÇö axios npm account hijacked to deliver RAT malware — Primary technical breakdown of the attack chain, dropper analysis, and C2 server identification. Published March 30, 2026.
- [2] Socket ΓÇö Supply chain alert: axios 1.14.1 and 0.30.4 contain malware — Socket automated detection report with exact UTC timestamps. Published March 31, 2026.
- [3] StepSecurity ΓÇö Malicious postinstall in plain-crypto-js@4.2.1 — Independent confirmation report from StepSecurity covering payload delivery mechanics.
- [4] npm ΓÇö axios package page (official) — npm registry entry confirming malicious versions were removed and resolution of the incident.
- [5] axios GitHub repository — GitHub history confirming no official tags or commits correspond to versions 1.14.1 or 0.30.4.