I first read about this on March 31, sitting at Changi Airport on my way back from RSAC. Two malicious versions of Axios had been live on the npm registry overnight. By the time I landed, npm had pulled the packages, but a lot of machines had already been infected.
Figure 1 - The GitHub issue created by the Axios Maintainer post identification of the compromise. Axios GitHub Issue..
On March 31, two malicious versions of Axios were published to the npm registry. They were live for roughly three hours. Any developer that ran npm install on a project depending on Axios, during that window pulled the malicious versions and ended up with a remote access trojan running on the machine.
Axios is a JavaScript library that apps and websites use to make HTTP requests such as fetching data from APIs, submitting forms, the kind of thing almost every web application has to do. To understand the scale of the incident; Axios is downloaded roughly 100 million times a week, around 174,000 other npm packages list it as a dependency. The two malicious versions were live on the registry for about three hours, and Huntress recorded the first confirmed infection on a customer machine less than 2 minutes after the first compromised release was published.
Like most open source projects, Axios is also aintained by a very small number of people, and the lead maintainer holds the credentials needed to publish new versions to npm registry. The threat actor group identified as the culprints of this attack, a North Korean state-sponsored group tracked as UNC1069, did not attempt to compromise npm itself. They just went after the maintainer directly.
The threat actor impersonated the founder of a company, they copied the founder's branding and public images, set up a private Slack workspace populated with fake employees, and added fake profiles of other open source maintainers to make the workspace look like a normal business environment. Eventually they invited the maintainer to a video call. During the call, a technical error was displayed which prompted the maintainer to install a Teams update, the maintainer installed it. The update was a piece of malware.
Once the malware was running, the attackers had remote control of the maintainer's laptop. They were not logging in from a new machine so two-factor authentication and OIDC trusted publishing did not apply. They were operating from inside the maintainer's pre-authenticated sessions. From npm's perspective, every activity looked like normal activity.
The threat actors published two new versions of Axios, 1.14.1 and 0.30.4. The only change in either version was a single new line added to package.json, declaring a dependency on a new package called plain-crypto-js. None of the actual Axios source code was modified.
The plain-crypto-js package was the payload delivery mechanism. The attackers published a clean version of it to npm a day earlier, so the package would have some publishing history when scanners looked at it, then updated it with the malicious code a few hours before publishing the poisoned Axios versions.
If somebody installed Axios during that window, npm quietly pulled in plain-crypto-js as a transitive dependency. The package shipped with a postinstall script that fired during installation: it reached out to the attacker's server, fetched a remote access trojan built for the host OS (Windows, macOS, or Linux), executed it, then wiped itself and swapped the package metadata for a clean copy. Anyone inspected node_modules/plain-crypto-js afterwards would have found nothing out of place.
The malicious versions were live on npm registry for just under three hours before the security community got them taken down. Huntress recorded the first confirmed infection on a customer machine 89 seconds after the first release was published, and counted 135 infected endpoints across their customer base before the takedown. The total number of affected systems across the wider ecosystem is unknown. Most of the impact would have been on developer laptops and CI build runners, which are rarely included in public incident reports.
The Axios maintainer did everything they were supposed to do. Two-factor authentication was enabled. The project had OIDC trusted publishing configured on the main release line, which is the recommended best practice for npm package security. None of these controls were bypassed. The attackers operated from inside an authenticated session, so the controls were never actually in effect. The only control that would have stopped this incident is a hardware FIDO2 security key for publishing, which a remote access trojan cannot use because it requires a physical button press on the device. npm does not currently allow projects to require hardware keys at the registry level.
Figure 2 - The Axios compromise, end-to-end attack chain. Threat actor through to victim install. The platform-specific payload delivery and C2 are covered separately in Figure 3.
UNC1069, also known as CryptoCore, is a financially motivated North Korean threat actor group that Mandiant has been tracking since 2018. Its assumed that the group sits under the DPRK's Recon General Bureau. According to Chainalysis, has stolen around $6.75 billion in cryptocurrency since 2017 - including roughly $2 billion in 2025 alone. This activity is widely believed to fund the North Korean regime and its weapons program.
Over the past few years, UNC1069 has specialised in long-running, individually targeted social engineering campaigns against cryptocurrency developers and open source project maintainers, often using AI-generated deepfakes during video calls. Kaspersky and Huntress documented the broader campaign in 2025 under the name GhostCall. The Axios compromise uses the same approach the group has been using against individual cryptocurrency organization employees, applied to a target with much wider impact.
The operation was carefully planned. The social engineering campaign ran for about two weeks. The decoy package was published 18 hours before the malicious Axios releases, and the C2 infrastructure was registered roughly eight hours before that. Both Axios release branches were poisoned within 39 minutes of each other. Every component of the dropper was designed to delete itself after execution.
The diff between the legitimate [email protected] and the malicious 1.14.1 is exactly one line in package.json:
Figure 3 - Actual diff between [email protected] and the malicious 1.14.1, captured from the npm registry before takedown. Source: Datadog Security Labs.
{
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0",
"plain-crypto-js": "^4.2.1" // ← this is the entire attack
}
}
plain-crypto-js itself is a typosquat of the real crypto-js, a literal clone with a scripts block bolted on so that npm install automatically runs node setup.js. The setup.js dropper (which GTIG tracks as SILKBELL) is heavily obfuscated using reversed Base64 and XOR. Once decoded, it does three things. Detects the host Operating system, downloads a platform specific second-stage payload from sfrclak[.]com:8000, and then deletes itself and replaces the malicious package.json with a clean copy shipped alongside the dropper as package.md. Inspecting node_modules/plain-crypto-js after execution shows nothing unusual. The only evidence is in the lockfile, the npm audit logs, and whatever limited telemetry the SOC was able to capture.
The second-stage payload is what GTIG identifies as WAVESHAPER.V2, a direct evolution of the original WAVESHAPER backdoor attributed to UNC1069. Elastic Security Labs makes an observation in their writeup that the the three stage-2 payloads are three platform-native implementations of a single cross-platform implant specification. PowerShell on Windows, a compiled Mach-O on macOS, and Python on Linux, all with the same C2 protocol, the same command set, the same 60-second beacon, and the same spoofed user-agent.
Figure 4 - DigitalBrainJS explaining the permission problem on GitHub issue #10604 - the compromised account had higher repo permissions than his own, so he could not revoke access directly. He worked around it by contacting npm directly. Source: Datadog Security Labs.
Three hours from the first malicious publish to npm, pulling the packages is a fast response for a supply chain compromise at this scale, and it was the result of a coordinated effort. Within 77 minutes of the first poisoned release, Axios collaborator DigitalBrainJS had opened PR #10591 to deprecate the compromised versions and had begun contacting npm directly. The compromised account had higher repository permissions than his own, so he could not revoke its access through the project itself and had to work around the attacker by escalating to npm.
The Axios compromise is not a new kind of attack. It is the same format as event-stream incident in 2018, ua-parser-js in 2021, the colors and faker incident in 2022, the PyTorch nightly incident in 2022, the Nx "s1ngularity" attack and the shai-hulud self-replicating npm worm in 2025, and several smaller incidents in between. The details change but the pattern does not. AN open-source project maintainer is targeted, a trusted package is poisoned, and the malicious version reaches production through a delivery mechanism that most defenders do not have visibility. The practical lessons from this attack are worth carrying forward into the next one, because there will be another one for sure.
The open-source project maintainers are the attack surface. For any packages the security of the project is inseparable from the security of the person publishing and managing it. Their laptop, their browser session, their inbox, and their working environment are all part of the supply chain.
2FA and OIDC do not cover such attacks. Both controls protect the logins. It doesnt help once an attacker is operating from inside an authenticated session on a trusted device. This is how Axios happened, and it is how most modern maintainer compromises happen. Hardware FIDO2 for publishing is the only credential control that addresses this class of attack, and it cannot be enforced at the npm registry level today.
Half-adopted security controls are worse than none. Axios had OIDC trusted publishing on v1.x, but the v0.x line still carried a long-lived classic token. That one forgotten credential compromised the entire project. .
Postinstall hooks are a backdoor by design. Arbitrary code execution on every npm install, with no sandboxing, is the single largest structural flaw in the ecosystem. Disabling lifecycle scripts with --ignore-scripts in CI is there, and most builds do not actually need them.
Speed of propagation is the actual problem. Huntress recorded the first infection 89 seconds after publish. Three hours of exposure infected 135 endpoints in just one vendor's telemetry. Any control that depends on a human analyst reading a vendor blog post and then acting on it is already too slow for this class of events.
A direct breach compromises one organisation. A supply chain breach compromises everyone downstream of a single point of trust, and the downstream list is usually invisible to the defender until the incident is already in progress. When event-stream was compromised, the target was a specific Bitcoin wallet application. When colors and faker were sabotaged, the blast radius included thousands of production builds that had never deliberately taken a dependency on either package. The victims did not pick these libraries directly. Their framework did, or their framework's framework did, and the trust was inherited silently.
1 compromised maintainer, 174K packages listing Axios as a dependency, 100M weekly downloads, 89 Seconds to first confirmed infection.
Figure 5 - The blast radius of a single supply chain compromise. Trust is inherited transitively, so victims do not need to have chosen the compromised package directly for it to end up inside their build.
The regulatory and commercial weight of this has caught up in the last two years. SBOM requirements, secure software development frameworks, and customer-facing assurances about upstream dependency management are now routine in enterprise procurement.
An organisation that cannot answer "which of our services depended on [email protected] during the exposure window" inside the first business hour of an incident has a problem that is larger than the incident itself.
npm is not uniquely insecure, but it hase certain properties that make it the most attractive target of any package ecosystem in use today. Scale is the obvious one. It is the largest public registry by volume, with the widest reach into enterprise build pipelines, cloud services, desktop applications, and anything else that has a JavaScript runtime in it.
A single package can touch more production systems in an hour than a traditional phishing campaign can in a month.
The JavaScript ecosystem favours small, single-purpose packages, which means dependency graphs are deep and wide. Most production applications pull in thousands of transitive dependencies, and almost no team has read even a tenth of that code.
Such incidents are nothing new. event-stream (2018) was kind of the beginning. ua-parser-js (2021) showed how far a single account takeover could reach. colors and faker (2022) were sabotaged by their own maintainer. Nx "s1ngularity" (August 2025) scraped developer credentials into public repos. Then shai-hulud (September 2025) became the first self-replicating npm worm, and shai-hulud 2.0 (November 2025) returned with preinstall execution and a 25,000-repo blast radius. Axios is the next entry on that list.
Reading a post-mortem incident report does not close gaps, running such scenario against your own environment does. Most organisations only exercise the technical side of an incident response when they are already responding to a real one, which is exactly when outdated runbooks, invalid detections, and unknown attacker techniques cause the most damage.
Continuous adversary simulation is the practice of running realistic end-to-end attack scenarios against your own infrastructure on an ongoing basis, so that the first time the security team encounters a technique is not in production.
Security control validation is the complementary discipline. Small, repeatable, automated tests that confirm each individual detection and prevention in the stack still fires when it should. Adversary simulation answers whether the overall defense would hold. Both practices catch different failures and issues. Adversary simulation identifies problems in coordination, escalation, and response. Control validation identifies lack of detections, misconfigurations, and silent failures in security products that were assumed to be working.
For a supply chain scenario such as the Axios compromise, the attack simulation exercises worth running against your own environment are the following.
Replay the C2 server reverse connection pattern from a build runner. Make a controlled outbound connection from a CI environment to a previously unseen domain and verify that network telemetry catches it.
Simulate a compromised internal package publish. Publish a harmless internal package with a postinstall hook that calls a known telemetry endpoint, then measure how long it takes the detection products and rules to flag it.
Tabletop the three-hour exposure window. Perform a Table-to exercise for the incident response team and walk them through the real incident timeline. Identify who has the authority to pull the package from internal mirrors, and how quickly the security team can identify which production services depend on the affected package.
Test the IOC ingestion pipeline. When new indicators from a real incident land in threat intel feeds, measure how long they take to propagate into the SIEM, the EDR, and other security products. The activity should be automated and not dependent on a ransom security analyst noticing a vendor blog post.
Practise the 'project maintainer as a target' scenario. The Axios compromise started with social engineering. Adversary simulation scenarios that include the human side, such as fake recruiter outreach, fake collaboration invites, and fake update prompts during video calls, give developers and maintainers in your own organisation a chance to recognise the pattern.
Exercise the SBOM query. Pick a recently disclosed upstream incident and time how long it takes to answer "are we affected" with certainty. The answer should be minutes not a working day or weeks.
Run these attack simulation scenarios on a schedule, repeatedly. The value increases when the same scenario is repeated, because the gaps identified on the second and third run are the ones that configuration changes introduced since the first run. That is the entire point of doing this continuously.
This is the area BreachSimRange focuses on. We build breach simulation scenarios, table-top exercises, red team engagements, and security control validation suites that target supply chain compromises, ransomware operations, and DPRK-style targeted intrusion campaigns, and we run them against the kinds of enterprise environments organisations actually operate. If this is something your security programme is working on, get in touch with us.
It is tempting to read an incident like this as a failure of the project's security practices, but that is not what happened here. The Axios maintainer had been running the project well for years. The compromise succeeded because a state-sponsored adversary spent two weeks running a targeted social engineering campaign against one specific person, and that was enough.
Most of the open source packages that modern software depends on are maintained by one or two people in their spare time, without proper security support and resources. The current model relies on individual maintainers to defend themselves against adversaries who have professional resources to back them. That is not a good position to be in, and the Axios incident is unlikely to be the last which leads to a serious compromise.