Skip to content
AI Primer
breaking

Report: axios@1.14.1 reportedly ships credential-stealing payload

Security researchers said axios 1.14.1 pulled in a malicious dependency and published indicators of compromise as warnings spread across npm and CI workflows. Check indirect and unpinned installs now, since the package sits deep in many JavaScript dependency trees and can run hostile code before teams notice.

5 min read
Report: axios@1.14.1 reportedly ships credential-stealing payload
Report: axios@1.14.1 reportedly ships credential-stealing payload

TL;DR

  • Security researchers and the axios maintainers said malicious versions axios@1.14.1 and axios@0.30.4 were published to npm on March 31 through a compromised maintainer account, then pulled a few hours later early GitHub alert first warning tweet.
  • The poisoned releases did not hide malware in axios source files. They added a new dependency, plain-crypto-js@4.2.1, whose postinstall hook fetched OS-specific payloads from sfrclak.com and then tried to clean up after itself issue screenshot IOC link tweet.
  • The blast radius was broader than teams that knowingly depend on axios, because 1.14.1 was tagged as latest, the package sits deep in JavaScript dependency trees, and fresh installs in CI could resolve to the bad version without a direct package change Karpathy on unpinned deps warning on indirect installs.
  • Published indicators included the C2 domain sfrclak.com, port 8000, and filesystem artifacts such as /Library/Caches/com.apple.act.mond on macOS, which is why incident responders were telling developers to treat affected machines as compromised, not merely broken IOC warning thread full IOC link.

You can read the initial GitHub issue, the maintainer's later postmortem, StepSecurity's technical writeup, Datadog's attack-flow breakdown, and Google's threat intel report. The weird detail is how little changed in axios itself: Datadog says the 1.14.1 source was effectively identical to 1.14.0, with the real payload arriving through one extra dependency and an install script.

What happened

The first public alarm landed fast. A GitHub issue opened at 03:00 UTC warned that axios@1.14.1 and axios@0.30.4 were compromised, and tweets started spreading the warning minutes later early GitHub alert first warning tweet.

According to Datadog Security Labs, the attacker published 1.14.1 at 00:21 UTC and 0.30.4 around 01:00 UTC. The malicious versions stayed live until about 03:15 to 03:25 UTC, depending on the source. Datadog says 1.14.1 was tagged as latest, while the 0.x line was published as legacy, which gave the attack reach into both modern installs and older compatibility ranges.

The package that actually carried the backdoor was plain-crypto-js@4.2.1. StepSecurity and Google both say it was never imported by axios application code, which is the whole trick: the dependency existed to run during installation, not runtime.

The install path

The install chain was short:

  1. npm install axios or an indirect dependency resolution pulled axios@1.14.1 or 0.30.4.
  2. Axios pulled plain-crypto-js@4.2.1.
  3. plain-crypto-js ran node setup.js through a postinstall hook.
  4. setup.js fetched a platform-specific second stage from http://sfrclak.com:8000/6202033.
  5. The script attempted to delete itself and restore a clean package.json to reduce obvious traces.

Google's analysis says the macOS path dropped a Mach-O binary at /Library/Caches/com.apple.act.mond, Windows used a copied PowerShell or Windows Terminal path under %PROGRAMDATA%, and Linux fetched a Python backdoor to /tmp/ld.py. The linked IOC gist matches the same domain, port, and macOS artifact.

Where the blast radius came from

Axios is one of the most common HTTP clients in the JavaScript ecosystem. The npm package page shown in the early screenshots lists more than 83 million weekly downloads npm package screenshot, and Datadog says the package has roughly 174,000 dependent npm packages.

That is why the warnings immediately focused on fresh installs, lockfile updates, and CI. Karpathy's example is the cleanest version of the problem: a project can declare axios loosely, resolve to a safe version one day, then pick up a poisoned latest release on the next install without any code change of its own Karpathy on unpinned deps.

The incident also hit people who never typed npm i axios. Wes Bos's warning, amplified across X, pointed at indirect installs, which is how a package like this usually spreads through build pipelines and developer laptops warning on indirect installs feross warning amplified.

Indicators and timeline

The public IOC set converged quickly. The linked gist and the Google report both name sfrclak.com on port 8000, campaign ID 6202033, and OS-specific dropped files including /Library/Caches/com.apple.act.mond on macOS and /tmp/ld.py on Linux IOC warning thread full IOC link.

The timeline from the maintainer postmortem adds the sequence behind the panic:

  • March 30, 05:57 UTC: plain-crypto-js@4.2.0 appears on npm.
  • March 31, 00:21 UTC: axios@1.14.1 is published with plain-crypto-js@4.2.1.
  • Around 01:00 UTC: axios@0.30.4 follows, and community members begin filing issues.
  • 01:38 UTC: axios collaborator DigitalBrainJS opens a PR to deprecate the compromised versions and contacts npm directly.
  • 03:15 UTC: the malicious axios releases are removed.
  • 03:29 UTC: plain-crypto-js is removed.

The maintainer postmortem

The most useful new detail came later. In the postmortem, lead maintainer Jason Saayman said the publish happened through his compromised personal account after a social engineering campaign that started about two weeks earlier. He also wrote that 2FA was enabled, but once the attacker had RAT-level access to the machine, they effectively had the same control he did.

That postmortem also explains a lot about the release path. Axios had trusted publishing set up, but the compromise still succeeded because publishing could still happen from the maintainer's account, not only from CI. The listed fixes are concrete: immutable releases, proper OIDC publishing, credential and device resets, and updated GitHub Actions workflows. The package incident is over, but the repo now reads like a case study in why high-download packages are moving away from laptop-based publishing.

Further reading

Discussion across the web

Where this story is being discussed, in original context.

On X· 2 threads
TL;DR1 post
Where the blast radius came from2 posts
Share on X