logoalt Hacker News

Axios compromised on NPM – Malicious versions drop remote access trojan

906 pointsby mtudtoday at 2:54 AM322 commentsview on HN

Comments

postalcodertoday at 4:05 AM

PSA: npm/bun/pnpm/uv now all support setting a minimum release age for packages.

I also have `ignore-scripts=true` in my ~/.npmrc. Based on the analysis, that alone would have mitigated the vulnerability. bun and pnpm do not execute lifecycle scripts by default.

Here's how to set global configs to set min release age to 7 days:

  ~/.config/uv/uv.toml
  exclude-newer = "7 days"

  ~/.npmrc
  min-release-age=7 # days
  ignore-scripts=true
  
  ~/Library/Preferences/pnpm/rc
  minimum-release-age=10080 # minutes
  
  ~/.bunfig.toml
  [install]
  minimumReleaseAge = 604800 # seconds
(Side note, it's wild that npm, bun, and pnpm have all decided to use different time units for this configuration.)

If you're developing with LLM agents, you should also update your AGENTS.md/CLAUDE.md file with some guidance on how to handle failures stemming from this config as they will cause the agent to unproductively spin its wheels.

show 16 replies
bob1029today at 8:50 AM

"Batteries included" ecosystems are the only persistent solution to the package manager problem.

If your first party tooling contains all the functionality you typically need, it's possible you can be productive with zero 3rd party dependencies. In practice you will tend to have a few, but you won't be vendoring out critical things like HTTP, TCP, JSON, string sanitation, cryptography. These are beacons for attackers. Everything depends on this stuff so the motivation for attacking these common surfaces is high.

I can literally count on one hand the number of 3rd party dependencies I've used in the last year. Dapper is the only regular thing I can come up with. Sometimes ScottPlot. Both of my SQL providers (MSSQL and SQLite) are first party as well. This is a major reason why they're the only sql providers I use.

Maybe I am just so traumatized from compliance and auditing in regulated software business, but this feels like a happier way to build software too. My tools tend to stay right where I left them the previous day. I don't have to worry about my hammer or screw drivers stealing all my bitcoin in the middle of the night.

show 6 replies
h4ch1today at 3:40 AM

I can't even imagine the scale of the impact with Axios being compromised, nearly every other project uses it for some reason instead of fetch (I never understood why).

Also from the report:

> Neither malicious version contains a single line of malicious code inside axios itself. Instead, both inject a fake dependency, [email protected], a package that is never imported anywhere in the axios source, whose only purpose is to run a postinstall script that deploys a cross-platform remote access trojan (RAT)

Good news for pnpm/bun users who have to manually approve postinstall scripts.

show 4 replies
nananana9today at 5:54 AM

Package managers are a failed experiment.

We have libraries like SQLite, which is a single .c file that you drag into your project and it immediately does a ton of incredibly useful, non-trivial work for you, while barely increasing your executable's size.

The issue is not dependencies themselves, it's transitive ones. Nobody installs left-pad or is-even-number directly, and "libraries" like these are the vast majority of the attack surface. If you get rid of transitive dependencies, you get rid of the need of a package manager, as installing a package becomes unzipping a few files into a vendor/ folder.

There's so many C libraries like this. Off the top of my head, SQLite, FreeType, OpenSSL, libcurl, libpng/jpeg, stb everything, zlib, lua, SDL, GLFW... I do game development so I'm most familiar with the ones commonly used in game engines, but I'm sure other fields have similarly high quality C libraries.

They also bindings for every language under the sun. Rust libraries are very rarely used outside of Rust, and C#/Java/JS/Python libraries are never used outside their respective language (aside form Java ones in other JVM langs).

show 10 replies
vsgherzitoday at 4:41 AM

Not to beat a dead horse but I see this again and again with dependencies. Each time I get more worried that the same will happen with rust. I understand the fat std library approach won’t work but I really still want a good solution where I can trust packages to be safe and high quality.

show 6 replies
himata4113today at 4:10 AM

I recommend everyone to use bwrap if you're on linux and alias all package managers / anything that has post build logic with it.

I have bwrap configured to override: npm, pip, cargo, mvn, gradle, everything you can think of and I only give it the access it needs, strip anything that is useless to it anyway, deny dbus, sockets, everything. SSH is forwarded via socket (ssh-add).

This limits the blast radius to your CWD and package manager caches and often won't even work since the malware usually expects some things to be available which are not in a permissionless sandbox.

You can think of it as running a docker container, but without the requirement of having to have an image. It is the same thing flatpak is based on.

As for server deployments, container hardening is your friend. Most supply chain attacks target build scripts so as long as you treat your CI/CD as an untrusted environment you should be good - there's quite a few resources on this so won't go into detail.

Bonus points: use the same sandbox for AI.

Stay safe out there.

show 8 replies
red_admiraltoday at 9:54 AM

There's a package manager discussion, but the bit that stands out to me is that this started with a credential compromise. At some point when a project gets big enough like axios, maybe the community could chip in to buy the authors a couple of YubiHSM or similar. I wish that _important keys live in hardware_ becomes more standard given the stakes.

Dealing with dependencies is another question; if it's stupid stuff like leftpad then it should be either vendored in or promoted to be a language feature anyway (as it has been).

show 1 reply
wpstoday at 4:31 AM

Genuinely how are you supposed to make sure that none of the software you have on your system pulls this in?

It’s things like this that make me want to swap to Qubes permanently, simply as to not have my password manager in the same context as compiling software ever.

show 3 replies
jadartoday at 3:34 AM

How much do you want to bet me that the credential was stolen during the previous LiteLLM incident? At what point are we going to have to stop using these package managers because it's not secure? I've got to admit, it's got me nervous to use Python or Node.js these days, but it's really a universal problem.

show 3 replies
tkeltoday at 5:01 AM

JS package managers (pnpm, bun) now will ignore postinstall scripts by default. Except for npm, it still runs them for legacy reasons.

You should probably set your default to not run those scripts. They are mostly unnecessary.

  ~/.npmrc :
  ignore-scripts=true

83M weekly downloads!
strogonofftoday at 6:27 AM

Essential steps to minimise your exposure to NPM supply chain attacks:

— Run Yarn in zero-installs mode (or equivalent for your package manager). Every new or changed dependency gets checked in.

— Disable post-install scripts. If you don’t, at least make sure your package manager prompts for scripts during install, in which case you stop and look at what it’s going to run.

— If third-party code runs in development, including post-install scripts, try your best to make sure it happens in a VM/container.

— Vet every package you add. Popularity is a plus, recent commit time is a minus: if you have this but not that, keep your eyes peeled. Skim through the code on NPM (they will probably never stop labelling it as “beta”), commit history and changelog.

— Vet its dependency tree. Dependencies is a vector for attack on you and your users, and any new developer in the tree is another person you’re trusting to not be malicious and to take all of the above measures, too.

show 2 replies
TheTaytaytoday at 10:05 AM

I know there is a cooldown period for npm packages, but I’m beginning to want a cooldown for domains too. According to socket, the C2 server is sfrclak[.]com, which was registered in the last 24 hours.

show 1 reply
woeiruatoday at 4:31 AM

Supply chain attacks are so scary that I think most companies are going to use agents to hard fork their own versions of a lot of these core libraries instead. It wasn’t practical before. It’s definitely much more doable today.

show 3 replies
majorbuggertoday at 7:52 AM

Good morning, or as they say in the NPM world, which package got compromised today?

jmward01today at 4:12 AM

This may not be popular, but is there a place for required human actions or just timed actions to slow down things like this? For instance, maybe a GH action to deploy requires a final human click and to change that to cli has a 3 day cooling period with mandatory security emails sent out. Similarly, you switch to read only for 6 hrs after an email change. There are holes in these ideas but the basic concept is to treat security more like physical security, your goal isn't always to 100% block but instead to slow an attacker for xxx minutes to give the rest of the team time to figure out what is going on.

show 1 reply
yoyohello13today at 5:28 AM

This is just going to get worse and worse as agentic coding gets better. I think having a big dependency tree may be a thing of the past in the coming years. Seems like eventually new malware will be coming out so fast it will basically be impossible to stop.

fluxisttoday at 8:20 AM

A command to recursively check for the compromised axios package version:

   find / -path '*/node_modules/axios/package.json' -type f 2>/dev/null | while read -l f; set -l v (grep -oP '"version"\s*:\s\*"\K(1\.14\.1|0\.30\.4)' $f 2>/dev/null); if test -n "$v"; printf '\a\n\033[1;31m FOUND v%s\033[0m  \033[1;33m%s\033[0m\n' $v (string replace '/package.json' '' -- $f); else; printf '\r\033[2m scanning: %s\033[K\033[0m' (string sub -l 70 -- $f); end; end; printf '\r\033[K\n\033[1;32m scan complete\033[0m\n'
show 1 reply
acheong08today at 4:39 AM

There are so many scanners these days these things get caught pretty quick. I think we need either npm or someone else to have a registry that only lets through packages that pass these scanners. Can even do the virustotal thing of aggregating reports by multiple scanners. NPM publishes attestation for trusted build environments. Google has oss-rebuild.

All it takes is an `npm config set` to switch registries anyways. The hard part is having a central party that is able to convince all the various security companies to collaborate rather than having dozens of different registries each from each company.

Rather than just a hard-coded delay, I think having policies on what checks must pass first makes sense with overrides for when CVEs show up.

(WIP)

show 2 replies
zar1048576today at 7:37 AM

In case it helps, we open-sourced a tool to audit dependencies for this kind of supply-chain issue. The motivation was that there is a real gap between classic “known vulnerability” scanning and packages whose behavior has simply turned suspicious or malicious. We also use AI to analyze code and dependency changes for more novel or generic malicious behavior that traditional scanners often miss.

Project: https://point-wild.github.io/who-touched-my-packages/

riteshkew1001today at 6:25 AM

Ran npm ci --ignore-scripts in our CI for months but never thought about local dev. Turns out that's the gap, your CI is safe but your laptop runs postinstall on every npm install.

The anti-forensics here are much more complicated that I had imagined. Sahring after getting my hands burned.

After the RAT deploys, setup.js deletes itself and swaps package.json with a clean stub. Your node_modules looks fine. Only way to know is checking for artifacts: /Library/Caches/com.apple.act.mond on mac, %PROGRAMDATA%\wt.exe on windows, /tmp/ld.py on linux. Or grep network logs for sfrclak.com.

Somehow noboady is worried about how agentic coding tools run npm install autonomously. No human in the loop to notice a weird new transitive dep. That attack surface is just getting worsened day by day.

mcintyre1994today at 7:22 AM

The frustrating thing here is that axios versions display on npmjs with verified provenance. But they don’t use trusted publishing: https://github.com/axios/axios/issues/7055 - meaning the publish token can be stolen.

I wrongly thought that the verified provenance UI showed a package has a trusted publishing pipeline, but seems it’s orthogonal.

NPM really needs to move away from these secrets that can be stolen.

raphinoutoday at 7:01 AM

I'm working on a multi signature solution that helps to detect unauthorized releases in the case of an account hijack. It is open source, self hostable, accountless and I am looking for feedback!

Website: https://asfaload.com/

GitHub:https://github.com/asfaload/asfaload

Spec: https://github.com/asfaload/spec

_pdp_today at 9:59 AM

I am not saying this is the reason for this compromise but the sudden explosion of coding assistant like claude code, and tools like openclaw is teaching entire crop of developers (and users) that it is ok to have sensitive credentials .env files.

wolvesechoestoday at 7:01 AM

I am glad I don't need to touch JS or web dev at all.

Now, I tend to use Python, Rust and Julia. With Python I am constantly using few same packages like numpy and matplotlib. With Rust and Julia, I try as much as possible to not use any packages at all, because it always scares me when something that should be pretty simple downloads half of the Internet to my PC.

Julia is even worse than Rust in that regard - for even rudimentary stuff like static arrays or properly namespaced enums people download 3rd party packages.

show 2 replies
jruohonentoday at 8:20 AM

So the root cause was again a developer's opsec. For improving things, I haven't seen many new initiatives on that side (beyond 2FA, but even that seems unenforced in these repositories, I reckon).

Ciantictoday at 9:09 AM

NPM should learn from Linux distribution package managers.

Have a branch called testing, and packages stay in testing for few weeks, after which they go to stable. That is how many Linux distributions handle packages. It would have prevented many of these.

Advising every user of npm/pnpm to change their settings and set their own cooldown periods is not a real choice.

show 2 replies
Suractoday at 5:03 AM

All these supply chain attacks make me nervous about the apps I use. It would be valuable info if an app used such dependencies, but on the other hand, programmers would cut their sales if they gave you this info.

bluepetertoday at 4:14 AM

Min release age sucks, but we’ve been here before. Email attachments used to just run wild too, then everyone added quarantine delays and file blocking and other frictions... and it eventually kinda/sorta worked. This does feel worse, though, with fewer chokepoints and execution as a natural part of the expectation.

Edit: bottom line is installs are gonna get SOOO much more complicated. You can already see the solution surface... Cooling periods, maintainer profiling, sandbox detonation, lockfile diffing, weird publish path checks. All adds up to one giant PITA for fast easy dev.

show 1 reply
bodashtoday at 9:08 AM

Some great tips in this thread and I've been collecting them all at https://github.com/bodadotsh/npm-security-best-practices

cleansytoday at 8:22 AM

To have an initial smoke test, why not run a diff between version upgrades, and potentially let an llm summarise the changes? It’s a baffling practice that a lot of developers are just blindly trusting code repos to keep the security standards. Last time I installed some npm package (in a container) it loaded 521 dependencies and my heart rate jumped a bit

show 1 reply
OlivOnTechtoday at 6:53 AM

The attacker went through the hassle to compromise a very widely used package, but use a non standard port (8000) on their C2... If you plan to do something like that, use 443 at least, many corporate network do not filter this one ;)

pjmlptoday at 5:49 AM

The amount of people still using this instead of fetch. Nonetheless when wasn't axios, it would be something else.

This is why corporations doing it right don't allow installing the Internet into dev machines.

Yet everyone gets to throw their joke about PC virus, while having learnt nothing from it.

show 2 replies
Hackbratentoday at 7:28 AM

I am now migrating all my unencrypted secrets on my machines to encrypted ones. If a tool supports scripted credential providers (e.g. aws-cli or Ansible), I use that feature. Otherwise, I wrap the executable with a script that runs gpg --decrypt and injects an environment variable.

That way, I can at least limit the blast radius when (not if) I catch an infostealer.

aizktoday at 6:34 AM

In light of these nonstop supply chain attacks: Tonight I created /supply-chain-audit -- A simple claude code skill that fetches info on the latest major package vulnerability, then scans your entire ~/ and gives you a report on all your projects.

https://github.com/IsaacGemal/claude-skills

It's a bit janky right now but I'd be interested to hear what people think about it.

show 1 reply
hyperadvancedtoday at 6:26 AM

Just sanity checking - if I only ever install axios in a container that has no secrets mounted in to its env, is there any real way I can get pwned by this kind of thing?

show 1 reply
lepuskitoday at 7:15 AM

I believe compartmentalized operating systems like Qubes are the future for defending against these kinds of attacks.

Storing your sensitive data on a single bare-metal OS that constantly downloads and runs packages from unknown maintainers is like handing your house key out to a million people and hoping none of them misuse it.

webprofusiontoday at 8:54 AM

My first thought was does VS Code Insiders use it (or anything it relies on, or do any extensions etc). Made me think.

mtudtoday at 2:54 AM

Supply chain woes continue

show 2 replies
koolbatoday at 3:28 AM

> Both versions were published using the compromised npm credentials of a lead axios maintainer, bypassing the project's normal GitHub Actions CI/CD pipeline.

Doesn’t npm mandate 2FA as of some time last year? How was that bypassed?

show 1 reply
neyatoday at 6:56 AM

I wonder if this has any connection with the recent string of attacks including the FBI director getting hacked. The attack surface is large, executed extremely cleanly - almost as if done by a high profile state sponsored actor, just like in Hollywood movies.

dinakerneltoday at 8:30 AM

Default setting latest should be caught in every static code scanner. How many times has this issue been raised.

dhruv3006today at 4:17 AM

174025 dependents.

kush3434today at 10:44 AM

first day at hacker news and this is the first post i saw

sgttoday at 7:43 AM

Is this an issue for those only using axios on the frontend side like in a VueJS app?

show 1 reply
ArtinOrtoday at 10:09 AM

Reset the clock

silverwindtoday at 8:47 AM

npm really needs to provide a options to set individual packages to only be publishable via trusted publishing.

maelitotoday at 8:47 AM

Glad to be using native fetch.

leventhantoday at 5:28 AM

PSA: Make sure to set a minimum release age and pin versions where possible.

🔗 View 27 more comments