DEV Community

Victor Eduardo Oliveira
Victor Eduardo Oliveira

Posted on

Someone Backdoored axios on npm. Here is How to Check if You Were Hit

On March 31, 2026, two malicious versions of axios were published to npm: axios@1.14.1 and axios@0.30.4. Both were live for roughly three hours before npm pulled them down. During that window, anyone who ran npm install axios could have had a Remote Access Trojan (RAT) dropped silently on their machine or CI runner, with no errors and no warnings.

This post breaks down what happened, how the attack worked, and the exact commands to check if you were affected.


What happened

The attacker compromised the npm account of the primary axios maintainer. Using stolen credentials, they published two new releases across both the 1.x and 0.x branches within 39 minutes of each other. The account's registered email was quietly changed to an attacker-controlled ProtonMail address before the releases went out.

Here is what makes this attack stand out: there is zero malicious code inside axios itself. Both releases simply added one new runtime dependency to package.json: a package called plain-crypto-js@4.2.1, which had never appeared in any legitimate axios version.

When you ran npm install, npm resolved and installed that dependency automatically, which triggered its postinstall script and silently executed the dropper.

The malicious dependency: plain-crypto-js

plain-crypto-js@4.2.1 was staged 18 hours before the axios releases, by a separate attacker-controlled account. It masquerades as a clone of the legitimate crypto-js library, with an identical description and the real author's name in the manifest. Visually, it looks harmless. The only difference from the real package is a single extra field in package.json:

"scripts": {
  "test": "grunt",
  "postinstall": "node setup.js"
}
Enter fullscreen mode Exit fullscreen mode

That setup.js is a cross-platform RAT dropper.

What setup.js does

The dropper detects your operating system and then:

  • macOS: writes an AppleScript to /tmp, executes it via nohup osascript, downloads a binary to /Library/Caches/com.apple.act.mond (named to blend in with Apple system processes), makes it executable and launches it
  • Linux: fetches a Python script from the C2 server to /tmp/ld.py and runs it in the background
  • Windows: copies PowerShell to %PROGRAMDATA%\wt.exe (disguised as Windows Terminal), then uses a VBScript to silently fetch and execute a PowerShell payload

All of this runs in under two seconds from the moment npm install starts. The npm install itself exits with code 0 and shows no errors.

The anti-forensics layer

After launching the payload, the dropper:

  1. Deletes setup.js from node_modules/plain-crypto-js/
  2. Deletes the malicious package.json
  3. Renames a pre-staged clean stub (package.md) to package.json, which reports version 4.2.0 with no scripts

After the swap, running npm audit reveals nothing. Running npm list plain-crypto-js shows version 4.2.0. The only reliable on-disk evidence is the existence of the node_modules/plain-crypto-js/ directory, since this package was never a dependency of any real axios release.

A note on the publish metadata

Every legitimate axios 1.x release is published via GitHub Actions with npm's OIDC Trusted Publisher mechanism, meaning the publish is cryptographically tied to a verified workflow. axios@1.14.1 breaks that pattern entirely. There is no corresponding tag or commit in the axios GitHub repository. It was published manually using a stolen npm access token.


Am I affected?

The malicious versions were live between approximately 00:21 UTC and 03:15 UTC on March 31, 2026. If you did not run npm install (or a fresh npm ci) during that window, you were likely not hit.

Run through these steps to verify.

Step 1: Check for the malicious axios versions

npm list axios 2>/dev/null | grep -E "1\.14\.1|0\.30\.4"
grep -A1 '"axios"' package-lock.json | grep -E "1\.14\.1|0\.30\.4"
Enter fullscreen mode Exit fullscreen mode

No output means you are probably fine. Any output means those versions were installed.

Step 2: Check for plain-crypto-js in node_modules

ls node_modules/plain-crypto-js 2>/dev/null && echo "POTENTIALLY AFFECTED"
Enter fullscreen mode Exit fullscreen mode

If the directory exists, the dropper ran. Do not rely on the version number inside it.

Step 3: Check for RAT artifacts on the system

macOS

ls -la /Library/Caches/com.apple.act.mond 2>/dev/null && echo "COMPROMISED"
Enter fullscreen mode Exit fullscreen mode

Linux

ls -la /tmp/ld.py 2>/dev/null && echo "COMPROMISED"
Enter fullscreen mode Exit fullscreen mode

Windows (cmd.exe)

dir "%PROGRAMDATA%\wt.exe" 2>nul && echo COMPROMISED
Enter fullscreen mode Exit fullscreen mode

Step 4: Check for C2 activity in logs

grep -r "sfrclak.com" ~/.npm/_logs/ 2>/dev/null
grep "sfrclak" ~/.bash_history ~/.zsh_history 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

Step 5: Check your CI/CD pipelines

Review any npm install runs in GitHub Actions or other CI systems between 00:20 UTC and 03:15 UTC on March 31. Any pipeline that ran with those axios versions should be treated as compromised, and all secrets injected in that workflow should be rotated immediately.

If you got multiple projects running

for dir in ~/projects/*/; do
  if [ -f "$dir/package.json" ]; then
    result=""
    if ls "$dir/node_modules/plain-crypto-js" 2>/dev/null | grep -q .; then
      result="DROPPER FOUND"
    fi
    axios_hit=$(grep -A1 '"axios"' "$dir/package-lock.json" 2>/dev/null | grep -E "1\.14\.1|0\.30\.4")
    if [ -n "$axios_hit" ]; then
      result="$result | MALICIOUS AXIOS VERSION"
    fi
    if [ -n "$result" ]; then
      echo "⚠️  $dir$result"
    else
      echo "✅  $dir"
    fi
  fi
done
Enter fullscreen mode Exit fullscreen mode

Remediation

1. Downgrade to a safe version

# 1.x users
npm install axios@1.14.0

# 0.x users
npm install axios@0.30.3
Enter fullscreen mode Exit fullscreen mode

2. Pin the version in your package.json

{
  "overrides":   { "axios": "1.14.0" },
  "resolutions": { "axios": "1.14.0" }
}
Enter fullscreen mode Exit fullscreen mode

3. Remove plain-crypto-js and reinstall

rm -rf node_modules/plain-crypto-js
npm install --ignore-scripts
Enter fullscreen mode Exit fullscreen mode

4. Block the C2 domain (macOS / Linux)

echo "0.0.0.0 sfrclak.com" | sudo tee -a /etc/hosts
sudo iptables -A OUTPUT -d 142.11.206.73 -j DROP
Enter fullscreen mode Exit fullscreen mode

5. Add --ignore-scripts to your CI installs going forward

npm ci --ignore-scripts
Enter fullscreen mode Exit fullscreen mode

This prevents any postinstall hook from running during automated builds, which would have stopped this attack entirely.


If you found a RAT artifact

Do not try to clean the machine in place. Rebuild from a known-good state and rotate everything that was accessible during the compromised install: npm tokens, AWS access keys, SSH private keys, cloud credentials, CI/CD secrets, and any .env values present at install time.


Indicators of Compromise

Category Value
Malicious packages axios@1.14.1, axios@0.30.4, plain-crypto-js@4.2.1
C2 domain sfrclak.com
C2 IP 142.11.206.73
C2 port 8000
macOS artifact /Library/Caches/com.apple.act.mond
Linux artifact /tmp/ld.py
Windows artifact %PROGRAMDATA%\wt.exe
Safe 1.x version axios@1.14.0 (shasum 7c29f4cf2ea91ef05018d5aa5399bf23ed3120eb)

Takeaways

This attack did not require any vulnerability in axios itself. It exploited the trust developers place in a well-known package name and a familiar maintainer account. The entire weapon was a single extra line in package.json.

A few habits that would have reduced exposure here:

  • Run npm ci --ignore-scripts in CI pipelines as a standing policy
  • Use npm's Trusted Publisher provenance statements to verify releases were published from the expected CI workflow
  • Watch for new dependencies appearing in transitive installs that were not there before
  • Pin your lockfile and review package-lock.json diffs in pull requests

The full technical breakdown, including the decoded dropper, process tree, and file swap events captured at runtime, is in the StepSecurity report.

Stay safe.

Top comments (0)