SuperAPI AI Directory

security-axios

Security & auditing

View repository

Updated 10-15 20:06

About this skill

Security: Axios Supply-Chain Attack Scanner

Mission

Scan the entire Mac for the axios npm supply-chain compromise (2026-03-31). Check package.json and all lock files (package-lock.json, yarn.lock, pnpm-lock.yaml). Detect anti-forensics (dropper self-cleanup), related campaign packages, and verify RAT SHA256. Produce a full HTML threat report and open it automatically.

Background

On 2026-03-31, axios versions 1.14.1 and 0.30.4 were published via a compromised maintainer account (jasonsaayman, email changed to ifstap@proton.me) with an injected dependency plain-crypto-js@4.2.1. Its postinstall hook (setup.js) deployed a cross-platform RAT that beacons to sfrclak[.]com:8000 every 60 seconds. On macOS the RAT binary is /Library/Caches/com.apple.act.mond. The dropper self-destructs after execution: setup.js is deleted and package.json is replaced with a clean stub reporting version 4.2.0 — so post-infection node_modules inspection will NOT reveal the malicious manifest. The directory presence of node_modules/plain-crypto-js/ alone confirms the dropper ran.

The malicious dependency was pre-staged ~18 hours earlier by attacker account nrwise (nrwise@proton.me). A clean decoy version (4.2.0) was published first to build registry history. Both compromised axios versions were published manually with a stolen npm token — no OIDC Trusted Publisher binding, no gitHead, no corresponding GitHub commit or tag.


References

Source URL
Snyk Advisory https://snyk.io/blog/axios-npm-package-compromised-supply-chain-attack-delivers-cross-platform/
Wiz Blog https://www.wiz.io/blog/axios-npm-compromised-in-supply-chain-attack
StepSecurity Blog https://www.stepsecurity.io/blog/axios-compromised-on-npm-malicious-versions-drop-remote-access-trojan
Aikido Blog https://www.aikido.dev/blog/axios-npm-compromised-maintainer-hijacked-rat
GitHub Issue #10604 https://github.com/axios/axios/issues/10604
GitHub Advisory https://github.com/advisories/GHSA-fw8c-xr5c-95f9
OSV Advisory https://osv.dev/vulnerability/MAL-2026-2306
Elastic Security Gist https://gist.github.com/joe-desimone/36061dabd2bc2513705e0d083a9673e7

Threat Intelligence

Category Value
Compromised axios versions 1.14.1, 0.30.4
Malicious dependency plain-crypto-js@4.2.1
Related campaign packages @shadanai/openclaw (v2026.3.28-2, 2026.3.28-3, 2026.3.31-1, 2026.3.31-2), @qqbrowser/openclaw-qbot (v0.0.130)
macOS RAT binary /Library/Caches/com.apple.act.mond
macOS RAT SHA256 92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a
Windows RAT %PROGRAMDATA%\wt.exe (PowerShell copy), %TEMP%\6202033.ps1, %TEMP%\6202033.vbs
Windows RAT SHA256 617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101 (PS1)
Linux RAT /tmp/ld.py
Linux RAT SHA256 fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf
C2 domain sfrclak[.]com
C2 IP 142.11.206.73
C2 port 8000
Campaign path /6202033
C2 POST body (macOS) packages.npm.org/product0
C2 POST body (Windows) packages.npm.org/product1
C2 POST body (Linux) packages.npm.org/product2
Infection vector npm install / yarn install / pnpm install postinstall hook
Compromised account jasonsaayman (email changed to ifstap@proton.me)
Attacker account nrwise (nrwise@proton.me) — published plain-crypto-js
GitHub Advisory GHSA-fw8c-xr5c-95f9
OSV Advisory MAL-2026-2306
Attack window 2026-03-31 00:21–03:15 UTC (~3 hours)
Windows persistence Registry Run key MicrosoftUpdate, re-download batch file
macOS dropper method AppleScript via osascript writing to /tmp/6202033

Package SHA256 Hashes

Package SHA256
axios-1.14.1.tgz 5bb67e88846096f1f8d42a0f0350c9c46260591567612ff9af46f98d1b7571cd
axios-0.30.4.tgz 59336a964f110c25c112bcc5adca7090296b54ab33fa95c0744b94f8a0d80c0f
plain-crypto-js-4.2.1.tgz 58401c195fe0a6204b42f5f90995ece5fab74ce7c69c67a24c61a057325af668
com.apple.act.mond (macOS) 92ff08773995ebc8d55ec4b8e1a225d0d1e51efa4ef88b8849d0071230c9645a
stage2.ps1 (Windows) 617b67a8e1210e4fc87c92d1d1da45a2f311c08d26e89b12307cf583c900d101
ld.py (Linux) fcb81618bb15edfdedfb638b4c08a2af9cac9ecfa551af135a8402bf980375cf

Package SHA1 Shasums (npm)

Package SHA1
axios@1.14.1 2553649f232204966871cea80a5d0d6adc700ca
axios@0.30.4 d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71
plain-crypto-js@4.2.1 07d889e2dadce6f3910dcbc253317d28ca61c766

Anti-Forensics Awareness

The dropper (setup.js) performs three cleanup actions after execution:

  1. Deletes setup.js — fs.unlink(__filename) removes itself
  2. Deletes package.json — removes the manifest with "postinstall": "node setup.js"
  3. Renames package.md to package.json — a pre-staged clean stub reporting version 4.2.0

Post-infection, npm list shows plain-crypto-js@4.2.0 (not 4.2.1). Incident responders checking for version 4.2.1 may incorrectly conclude the system is clean. The reliable check is directory presence: if node_modules/plain-crypto-js/ exists at all, the dropper ran — this package is not a dependency of ANY legitimate axios version.

Our scanner checks:

  • node_modules/plain-crypto-js/ directory existence (confirms dropper ran)
  • node_modules/plain-crypto-js/setup.js presence (dropper not yet cleaned up)

Execution Flow

GREP PRE-FILTER → PARSE → LOCK FILES → RELATED PKGS → IOC CHECK → SHA256 VERIFY → LAUNCH PERSIST → REPORT → OPEN

What Is Scanned

File / Check What We Check
package.json declared axios version, plain-crypto-js in all dep sections, related campaign packages
package-lock.json resolved axios version, plain-crypto-js in packages tree, related campaign packages
yarn.lock resolved axios version, any mention of plain-crypto-js
pnpm-lock.yaml resolved axios version, any mention of plain-crypto-js
node_modules/plain-crypto-js/ directory presence (confirms dropper ran even after self-cleanup)
node_modules/plain-crypto-js/setup.js dropper file still present (not yet cleaned up)
/Library/Caches/com.apple.act.mond RAT binary present + SHA256 hash verification against known IOC
running processes via pgrep RAT process (FP-safe — pgrep excludes itself)
lsof -i active C2 connection to sfrclak.com or 142.11.206.73
~/Library/LaunchAgents/, /Library/LaunchAgents/, /Library/LaunchDaemons/ launch persistence referencing act.mond, sfrclak, or C2 IP
global npm/yarn/pnpm plain-crypto-js installed globally

False-Positive Notes

Process check FP risk: NEVER use ps aux | grep act.mond — a bash heredoc containing that string would match itself. Use pgrep -f "/Library/Caches/com.apple.act.mond" instead — pgrep excludes its own PID, and the script runs as python3 /tmp/file.py (no script content in command line).

Anti-forensics version mismatch: After dropper cleanup, npm list plain-crypto-js reports 4.2.0 (not 4.2.1). The scanner checks directory existence rather than version number.


Scripts

The scanner is split into focused modules under scripts/:

skills/security-axios/scripts/
├── axios_scan.py    # Entry point — orchestrates scan, IOC check, report
├── constants.py     # Threat intel: IOC hashes, versions, references, skip dirs
├── scanners.py      # Manifest/lock file parsers + find_and_scan walker
├── ioc_check.py     # System IOC checks: RAT, C2, globals, launch persistence
└── report.py        # HTML report generation: CSS, tables, badges, template

To run:

python3 /Users/guybary/Documents/skills/skills/security-axios/scripts/axios_scan.py

Module Reference

constants.py — Threat Intelligence Data

All IOC constants, SHA256 hashes, related campaign packages, skip directories, and reference URLs.

scanners.py — Manifest & Lock File Parsers

Function Purpose
scan_package_json(path) Scan for axios, plain-crypto-js, and related campaign packages in all dep sections
scan_package_lock(path) Scan npm lockfile v1/v2/v7+ packages tree, including related packages
scan_yarn_lock(path) Regex-based scan for compromised resolved versions
scan_pnpm_lock(path) Regex-based scan for pnpm lockfile v5/v6/v9 formats
find_and_scan() Walk ~/, merge findings per repo, track dropper evidence (plain_installed, setup_js_present)
quick_hit(path, *needles) Bytes-level grep pre-filter before full parse
check_related_pkgs(all_deps) Check dependency map for @shadanai/openclaw, @qqbrowser/openclaw-qbot

ioc_check.py — System IOC Detection

Function Purpose
check_iocs() Returns (rat_found, rat_hash_match, rat_running, c2_active, global_crypto, launch_persist)
sha256_file(path) Compute SHA256 for IOC hash verification

Checks performed:

  • RAT binary existence + SHA256 verification against known hash
  • pgrep -f for running RAT process (FP-safe)
  • lsof -i for active C2 connections
  • npm/yarn/pnpm global list for plain-crypto-js
  • LaunchAgents/LaunchDaemons scan for persistence references

report.py — HTML Report Generation

Generates dark-themed HTML report with:

  • Threat intel section (SHA256 hashes, campaign path, advisory IDs)
  • Project tables with dropper evidence and related packages columns
  • Source badges (📦 package.json · 🔒 lockfile · 🧶 yarn · ⚡ pnpm)
  • References & Advisories section with all 8 source links
  • Remediation steps including version pinning and CI/CD --ignore-scripts
  • Footer with advisory links (GHSA, OSV, Snyk, Wiz, StepSecurity, Aikido)

Execution Instructions

When this skill is invoked:

  1. Announce — scanning for the axios supply-chain attack (2026-03-31).

  2. Run the scanner script directly — do NOT copy/paste inline:

python3 /Users/guybary/Documents/skills/skills/security-axios/scripts/axios_scan.py
  1. What the script does:

    • Walk ~/ skipping node_modules, Library, caches, etc.
    • Use bytes-level grep pre-filter before full JSON/YAML parsing (fast)
    • Scan package.json, package-lock.json, yarn.lock, pnpm-lock.yaml per repo
    • Check for related campaign packages (@shadanai/openclaw, @qqbrowser/openclaw-qbot)
    • Detect dropper anti-forensics (directory presence vs setup.js presence)
    • Check macOS IOC with pgrep -f RAT_PATH (NOT ps aux | grep — avoids FP)
    • SHA256 verify RAT binary against known hash 92ff0877...c9645a
    • Check C2 connections via lsof -i
    • Check global npm/yarn/pnpm for plain-crypto-js
    • Scan LaunchAgents/LaunchDaemons for persistence referencing attack IOCs
    • Generate dark-themed HTML with source badges (📦 🔒 🧶 ⚡) and all references
    • Open in browser automatically
  2. Print the terminal summary.

  3. Verdict:

    • 🚨 SYSTEM COMPROMISED — RAT binary / C2 active / launch persistence
    • ⚠ VULNERABLE DEPS FOUND — compromised axios in lock files / package.json
    • ✅ CLEAN — no compromised versions, no IOCs
  4. List each compromised repo with path, version, which file(s) confirmed it, and related packages.


Constraints

  • NEVER output credential values from any scanned file.
  • NEVER modify any files. Read-only scan.
  • Skip node_modules/ when walking for manifests.
  • FP rule: use pgrep -f RAT_PATH — never ps aux | grep act.mond.

Success Criteria

  • All package.json + lock files scanned (outside node_modules)
  • Compromised axios 1.14.1 / 0.30.4 detected in package.json AND lock files
  • plain-crypto-js@4.2.1 detected in all manifest types
  • Related campaign packages (@shadanai/openclaw, @qqbrowser/openclaw-qbot) detected
  • yarn.lock and pnpm-lock.yaml scanned for resolved versions
  • Anti-forensics detected (plain-crypto-js directory presence + setup.js check)
  • macOS RAT IOC checked (binary + SHA256 verification + pgrep process + lsof C2)
  • Launch persistence checked (LaunchAgents/LaunchDaemons)
  • Global npm/yarn/pnpm checked for plain-crypto-js
  • HTML report with source badges (📦 package.json · 🔒 lockfile · 🧶 yarn · ⚡ pnpm)
  • HTML report includes all 8 references (Snyk, Wiz, StepSecurity, Aikido, GitHub Issue, GHSA, OSV, Elastic)
  • HTML report includes SHA256 hashes and advisory IDs in threat intel section
  • Report auto-opened in browser
  • No false positives from process detection