A potential npm supply chain disaster was averted in record time after attackers took over a verified developer’s credentials.
On September 8, Josh Junon, a developer with over 1800 GitHub contributions in the last year, confirmed on Bluesky his npm account was compromised. Junon had been alerted by other users that his account had started posting packages with backdoors to all popular packages the developer was involved in.
The developer, commonly known as ‘qix,’ said he received an email to reset his two-factor authentication (2FA) that looked “very legitimate,” but that was malicious.
He added that it only involved his npm account and that he was in contact with NPM to resolve the issue.
Compromised npm Packages
The compromised ‘qix’ npm account published malicious versions for dozens of packages Junon was involved in.
These included some npm packages for high-volume JavaScript projects:
- chalk (approximately 300 million weekly downloads)
- strip-ansi (approximately 261 million weekly downloads)
- color-convert (approximately 193 million weekly downloads)
- color-name (approximately 191 million weekly downloads)
- error-ex (approximately 47 million weekly downloads)
- simple-swizzle approximately 26 million weekly downloads)
- has-ansi (approximately 12 million weekly downloads)
The payload implanted in the malicious packages is a crypto-clipper that steals funds by swapping wallet addresses in network requests and directly hijacking crypto transactions.
Crypto-Stealer Attack Chain Explained
This sophisticated malware targets cryptocurrency users through two main attack vectors.
First, it checks if a wallet extension (like MetaMask) is present. If not, it launches a passive address-swapping attack, intercepting all web traffic by hijacking the browser’s fetch and XMLHttpRequest functions. The malware then replaces legitimate crypto addresses with attacker-controlled ones, using the Levenshtein distance algorithm to pick the most visually similar address, making the swap nearly undetectable to the naked eye.
If a wallet is detected, the malware escalates to active transaction hijacking. It intercepts outgoing transactions (e.g., eth_sendTransaction) and modifies the recipient address in memory before the user signs it. The victim sees a legitimate-looking confirmation screen, but if they don’t verify the address carefully their funds are sent straight to the attacker.
The attack chain is stealthy and automated, exploiting both human perception (via address spoofing) and technical vulnerabilities (via wallet API manipulation). By compromising a trusted npm package, the malware spreads silently, infecting websites and stealing funds without raising immediate suspicion.
One of the primary Ethereum addresses used in the attack is 0xFc4a4858bafef54D1b1d7697bfb5c52F4c166976. People can see its activity live on Ethereum-scanning website Etherscan to traxksome of the stolen funds
A GitHub Gist listing all affected wallets has also been created.
An Averted Crisis that Should Be “Celebrated”
Four hours after Junon confirmed the compromise, he shared a message from NPM saying that all impacted package versions had been taken down.
While many people started calling this hack the “biggest supply chain attack in history” on social media, many voices have challenged this narrative.
Josh Bressers, VP of security at Anchore, said on LinkedIn: “Here’s the thing nobody seems to be talking about. This all lasted for only a few hours. It’s amazing how fast open source can respond to things like this. Everyone works together. Information can be shared. The number of people now working on this isn’t just larger than your security team, it’s larger than your company.”
Katie Paxton-Fear, an ethical hacker who recently started working as a staff security advocate at Semgrep, published a video on LinkedIn emphasizing that a major crisis has been averted.
“Obviously, any security breach is bad, but this is not the major security breach that people are making it out to be,” she said.
She highlighted that the estimated total loss only amounted to $20, thanks primarily to the rapid response of the open source community.
“The malware was noticed and people started talking about it on GitHub within only 15 minutes of the malicious packages going live. Some of the packages were taken down by maintainers just one hour after the compromise happened, and the rest of them by NPM within two hours,” she explained.
According to Arda Büyükkaya, a senior cyber threat intelligence analyst at EclecticIQ, the attacker’s crypto address shows $66.52.
Nevertheless, Paxton-Fear argued that this incident is “a win that shows that the open source model works and that should be celebrated.”
In another LinkedIn post, Melissa Bischoping, the director for endpoint security research at Tanium, went further: “If you’re panicking about that NPM thing, please don’t. There’s a virtually 0 chance you’re impacted by this, and you should not burn your teams by having them pick apart every corner of your infrastructure for evidence of these compromised packages.”
She continued: “These were up for a couple of hours on a Monday morning (US time) The chances of them being downloaded and shipped into your software in that window of time are very, very small – nearly 0. Of all of the things I think you should have your team pull late nights for, this isn’t one of them.”
How to Mitigate This Threat
However, those who still think they may be affected can take immediate action to block vulnerable dependencies.
According to Jan-David Stärk, a team lead and software engineer at Hansalog, to force-safe versions across an entire project, developers can use overrides in their package.json, by adding the following to pin trusted versions of the compromised packages:
{
“name”: “your-project”,
“version”: “1.0.0”,
“overrides”: {
“chalk”: “5.3.0”,
“strip-ansi”: “7.1.0”,
“color-convert”: “2.0.1”,
“color-name”: “1.1.4”,
“is-core-module”: “2.13.1”,
“error-ex”: “1.3.2”,
“has-ansi”: “5.0.1”
}
}
Then, developers should clean their project by deleting node_modules and package-lock.json, then run npm install to generate a fresh, secure lockfile.
This will ensure that no malicious versions remain in their dependency tree.