By clicking “Accept”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.
18px_cookie
e-remove
Blog
Glossary
Customer Story
Video
eBook / Report
Solution Brief

npm Account Takeovers are a Growing Malware Trend

npm Account Takeovers hit an all-time high in 2025. Learn why this malware attack vector is a big risk for open source software consumers.

npm Account Takeovers hit an all-time high in 2025. Learn why this malware attack vector is a big risk for open source software consumers.

npm Account Takeovers hit an all-time high in 2025. Learn why this malware attack vector is a big risk for open source software consumers.

Written by
Jenn Gile
Jenn Gile
Published on
January 29, 2026
Updated on
January 29, 2026

npm Account Takeovers hit an all-time high in 2025. Learn why this malware attack vector is a big risk for open source software consumers.

npm Account Takeovers hit an all-time high in 2025. Learn why this malware attack vector is a big risk for open source software consumers.

If you work in security, maybe you’ve spent years telling developers to watch out for typos in their package.json files. But in 2025, the threat model for npm shifted. While typosquatting and dependency confusion attacks remained dominant, we saw a concerning increase in Account Takeovers (ATOs).

An ATO is where an attacker gains access to a legitimate open source project and pushes a new version containing malware. The Endor Labs security research team verified that In 2025, 1241 npm packages were confirmed to be malicious—a 15.3x increase from 2024. While ATOs represent a minute percentage of total malware attacks, the volume is increasing and their impact is outsized.

Why is this attack vector so attractive to threat actors? Because ATOs target trusted projects and bypass almost every traditional security filter. If a package is trusted, signed, and has millions of downloads, most CI/CD pipelines and developer environments let it right through the front door.

Our research team discovered that within the npm ecosystem, 31.6% of compromised packages had over 1,000 monthly downloads and 13.9% exceeded 10,000 monthly downloads. Even when a malicious version only existed for just 48–72 hours before removal, the 4.6% of packages with 100k+ downloads could have been automatically pulled into thousands of pipelines. If your devs have an “always upgrade to latest” mentality, you are at high risk for consuming these compromised packages.

Let’s look at five campaigns from 2025 to understand this trend. 

A timeline of five ATO malware campaigns in 2025

ATO #1: eslint-config-prettier (July 18, 2025)

The first major offensive targeted the eslint-config-prettier package, which is a foundational component of the JavaScript linting ecosystem with over 30 million weekly downloads.

Attackers started with a phishing email, which may have been AI-generated to look believable or even used a phishing kit (now widely available, including logos and fonts to make this very easy). They sent this email (see below) with a typosquatted URL to maintainer JounQin, who clicked the link and in doing so, inadvertently provided the attacker with their npm token. 

Phishing email sent to the maintainer of eslint-config-prettier

The adversary never touched the official GitHub repository, meaning no suspicious commits or Pull Requests were visible to reviewers. Using the stolen token, the attacker published four malicious versions: 8.10.1, 9.1.1, 10.1.6, and 10.1.7. (Later analysis suggested version 10.1.6 was modified but did not contain the final payload.) 

These versions included a new install.js script and a node-gyp.dll file that triggered during npm install. The malware was designed for Remote Code Execution (RCE) and its primary functions included reconnaissance, data exfiltration (such as stealing SSH keys or AWS secrets), and establishing persistence on developer machines and CI/CD hosts. 

The impact of this initial 2025 ATO was mitigated by its restriction to Windows hosts, yet the scale of the downloads ensured that thousands of developer machines and CI/CD runners were likely compromised before the versions were removed. CVE-2025-54313 was assigned to the incident, highlighting the severity of the supply chain compromise.

ATO #2: is (July 19, 2025)

Just one day after the eslint-config-prettier attack, the is library was compromised. Using a slightly different phishing strategy, attackers spoofed npm support to trick the primary maintainer (Jordan Harband) into re-adding a former maintainer account they had already hijacked. According to Harband, the attackers claimed “that their account did not have 2FA set up, and that’s why it was removed” by npm.

Once the account was reactivated and restored to the package ownership list, the attackers had a clean entry point that didn't immediately alert Harband. The most alarming part of this compromise wasn't just a stolen password; it was the exploitation of npm’s account recovery and ownership flow to bypass the primary maintainer's security.

Social media posts by 'is' project maintainer about account compromise

Whether this is the same threat actors as eslint-config-prettier is not confirmed, but similarities in the phishing and malware imply it’s likely.

Attackers uploaded versions 3.3.1 and 5.0.0, which included a JavaScript malware loader. It represented a greater threat than the Windows-only DLL loader in eslint-config-prettier, since it could be executed on macOS, Linux, and Windows. It remained entirely in JavaScript and used a live command and control (C2) channel. 

The backdoor allowed the attacker to send arbitrary JavaScript strings to the infected machine, which were then executed using new Function(). This gave them a real-time, interactive shell into any developer machine or production server running the package. Attackers targeted exfiltrating environment variables.

The speed of this attack was designed to outrun manual verification:

  • 09:30 UTC: Malicious versions 3.3.1 and 5.0.0 are published.
  • 11:00 UTC: First community reports surface on GitHub as developers notice unexpected outbound network activity or checksum mismatches.
  • 15:30 UTC (Detection): The primary maintainer is alerted and confirms the versions were not published by him.
  • 18:00 UTC (Resolution): npm removes the malicious versions and revokes the compromised account's tokens.

The rapid lifecycle of the is compromise (just under 9 hours) emphasized the speed with which community-driven detection can operate. However, the incident also underscored the vulnerability of human-in-the-loop administrative decisions, which remain a significant weak point in the open-source trust model.

ATO #3: s1ngularity Nx (August 26, 2025)

The third attack in the series was made possible through a more unique attack vector: The attackers discovered that the Nx repository had a GitHub Actions injection vulnerability. Nx is a popular monorepo management tool with over 5.5 million weekly downloads, making it a critical hub for enterprise-scale software development.

The core issue was the use of the pull_request_target trigger in a specific workflow. While this trigger runs in the context of the base repository (providing access to secrets), the Nx workflow did not properly sanitize inputs from the pull request (specifically the PR title), allowing for command injection. An attacker created a pull request with a malicious title containing shell commands, and because the workflow ran commands using this unsanitized input with elevated permissions, the malicious code was executed within the GitHub Actions runner environment. The malicious script, once running with repository permissions, was able to access and exfiltrate the NPM_TOKEN which was available as a GitHub secret to a different, but associated, publish.yml workflow.

The attackers used this access to publish 8 core packages with a post-install script that triggered telemetry.js. And here’s where things get scary. telemetry.js searched the developer’s environment for locally installed AI tools (Claude, Gemini, and Amazon Q). Then it was able to bypass the AI safety measures with flags like --dangerously-skip-permissions, --yolo, and --trust-all-tools. This enabled them to abuse these highly-permissioned agents to find and harvest secrets. Secrets were dumped into repositories containing s1ngularity-repository-#####, hence the name for this attack is s1ngularity Nx.

In less than 8 hours, over 370 companies were identified as affected. Two days later, the second wave of the attack used harvested secrets to flip an estimated 6700 repos from private to public. More than 20,000 files were exfiltrated. The Nx team wrote a public postmortem on the incident that’s well worth the read.

A LinkedIn message from security researcher Paul McCarty to a compromised community member.

ATO #4: chalk & debug (September 8, 2025)

On September 8, 2025, the JavaScript community faced one of the largest incidents in its history when numerous foundational packages (including chalk and debug) were hijacked. These packages have billions of weekly downloads and are present as transitive dependencies in virtually every modern JavaScript application.

Attackers returned to the tried-and-true tactic of a phishing email. This time, they sent the maintainer Qix (Josh Junon) a support email from support@npmjs.help (a typosquatted domain registered just three days prior) threatening a temporary account lock if he didn’t reset his 2FA. The maintainer has publicly acknowledged that he should have known this was a trap, but was multitasking during a stressful week. He clicked the link, which led to a fraudulent login page that used an Adversary-in-the-Middle (AiTM) technique. It harvested his username, password, and a live TOTP (Time-based One-Time Password) code in real-time. Once the attackers had the live token, they immediately logged in, changed the account's recovery email to lock the maintainer out, and compromised up to 28 popular npm packages.

Phishing email targeting maintainer Josh Junon
Social media post from maintainer Josh Junon about the incident

The malware injected into these packages functioned exclusively within browser environments. It utilized sophisticated API hooking to monitor for cryptocurrency and Web3 activity. Specifically, it targeted the window.ethereum object used by wallets like MetaMask, as well as the standard fetch and XMLHttpRequest APIs. Technical details include:

  • Network Response Manipulation: The malware scanned API responses for blockchain addresses across multiple chains, including Ethereum, Bitcoin, Solana, and Litecoin.
  • Address Replacement: Using a Levenshtein "nearest match" algorithm, the malware replaced a user's intended recipient address with an attacker-controlled address that appeared visually similar to the original.
  • Redundancy: The code maintained over 280 hardcoded attacker addresses to ensure persistence if individual wallets were flagged or drained.

Despite the astronomical download numbers of the affected packages, the financial impact was reportedly minimal, with estimates ranging from $500 to $1,000 stolen. Researchers hypothesized that the campaign might have been a stress test or experiment for a future, more targeted offensive.

ATO #5: Shai-Hulud (Sept–Nov 2025)

Shai-Hulud was 2025’s Heartbleed or Log4Shell. But while those were logic flaws with the potential to be exploited, Shai-Hulud was 100% out to get you. 

On September 15, the maintainer techsupportrxnt credentials were used to access their GitHub account. It’s unknown exactly how the attackers got the credentials. Perhaps it was a phishing email or GitHub actions vulnerability, but perhaps more likely is that their credentials were stolen during the S1ngularity Nx incident. Regardless of the “how”, the outcome is essentially the same: Attackers gained access to 187 packages and published malware disguised as a color library that included malicious bundle.js. 

Here’s where the malware gets crafty. Like with S1ngularity Nx, where they weaponized AI tools, in this case the malware installed and weaponized the open source secret scanner TruffleHog. TruffleHog was tasked to find new npm tokens and the malware flipped 528 repos to public. 

To ensure maximum impact, the malware used worm-like behavior to automatically republished itself to any package the victim had rights to.

On November 21, the second wabve hit. Using credentials stolen during the 1st wave, attackers targeted at least 100 maintainers. They successfully hijacked 492 packages to deploy files named setup_bun.js and bun_environment.js in order to leverage the Bun runtime to evade standard security monitoring tools. This second wave also leveraged TruffleHog, but in an insulting twist, it also included a destructive fallback mechanism. If the worm failed to replicate or find exfiltratable secrets, it attempted to delete the victim's entire home directory. Furthermore, it established a persistent backdoor by installing a self-hosted GitHub runner named "SHA1HULUD" on the compromised machine, allowing for remote command execution via GitHub Discussions.

Shai-Hulud 2.0 exposed credentials from 26,300 repos, including those from high-profile companies like Postman and Zapier.

The link between s1ngularity Nx and Shai-Hulud

Researchers from several security companies identified that the s1ngularity Nx and Shai-Hulud attacks were likely orchestrated by the same threat actor or group. Both attacks used the victim's own GitHub account as a data dump, where they exfiltrated stolen secrets (like AWS keys and npm tokens) by forcing them into public repositories under the victim's name, likely to bypass firewalls that would block data sent to an unknown external server. 

We also saw both attacks use legitimate tools (AI code assistants, TruffleHog) to identify secrets on developer machines. Further, the malicious scripts in both attacks shared similar obfuscation techniques (double-base64 encoding) and used the same postinstall script hooks in package.json to trigger the malware.

npm security measures improved, but not enough to stem the tide

GitHub owns npm. In 2025, they took a lot of heat about the poor security controls in npm. And this is a fair complaint: It’s been much easier for malware attackers to use npm for ATOs than other ecosystems. At the top of this blog we shared that there were 1241 confirmed malicious npm packages in 2025. To contrast with another top ecosystem: In 2025, pypi only had 18 confirmed malicious packages, and they heavily skewed toward very low volume (10-99 monthly downloads).

GitHub made two major security improvements to npm in 2025: trusted publishing and session-based authorization.

Trusted Publishing (July 31, 2025)

Following the eslint-config-prettier and is ATOs, GitHub announced general availability for Trusted Publishing for npm. This feature enables maintainers to securely publish npm packages directly from CI/CD workflows using OpenID Connect (OIDC) for authentication, reducing the need to manage long-lived tokens.

The community has been excited about this capability, so kudos to GitHub! But let’s also acknowledge its limitations.

At present, Trusted Publishing is primarily built for GitHub Actions and GitLab CI/CD, so it may not work for repos using Bitbucket, Jenkins, or self-hosted runners. Meaning if a maintainer's workflow sits outside the supported integrations, they cannot adopt Trusted Publishing without migrating their entire infrastructure. And setting up OIDC tokens and configuring specific runners requires a level of DevOps maturity that many individual open-source maintainers lack.

Session-Based Authorization (December 9, 2025)

In December 2025, GitHub took an important step towards improving npm security by permanently revoking classic tokens and replacing them with session-based authorization, which limits stale token life to a short period.

Now again this is a great improvement, but it’s not a silver bullet. Session-based authorization would have prevented the second wave of Shai-Hulud from being possible to execute so long after the first wave (because the stolen tokens were expired). However, session-based authorization can still be phished. It reduces the amount of time that attackers have to log in and take over, but it doesn’t stop it. Further, as of this blog’s publication, it’s still possible to create an npm access token  with a 90 day timeframe.

Find out More

The Challenge

The Solution

The Impact

Welcome to the resistance
Oops! Something went wrong while submitting the form.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.