Massive NPM Attack Targets Most Popular Maintainers

Paul McCarty
10 mins
September 8, 2025

The background

A popular NPM maintainer was compromised today which led to 18 NPM packages having malicious packages published to the NPM registry.

The maintainer, Josh Junon, was successfully phished from an email purporting to be from NPM but really came from a lookalike domain "npmjs[.]help":

Once the maintainer was compromised, the threat actors rushed to push out malicious versions of his packages. Josh helps maintain some VERY popular packages and the impact was felt really quickly. The affected packages are downloaded over 2 billion times a week! This is a massive attack!

The affected packages and versions are:

ansi-regex - 6.2.1
ansi-styles - 6.2.2
backslash - 0.2.1
chalk - 5.6.1
chalk-template - 1.1.1
color-convert - 3.1.1
color-name - 2.0.1
color-string  - 2.1.1
debug - 4.4.2
error-ex - 1.3.3
has-ansi - 6.0.1
is-arrayish - 0.3.3
simple-swizzle - 0.2.3
slice-ansi  - 7.1.1
strip-ansi - 7.1.1
supports-color  - 10.2.1
supports-hyperlinks - 4.1.1
wrap-ansi - 9.0.1

What does this malware do?

Core Functionality: Crypto Address Swapping

The payload is in the src/index.js file which is heavily obfuscated.  The index.js file appears to be a crypto drainer and is targeting several common cryptocurrencies. The primary malicious action is to replace cryptocurrency wallet addresses found on websites with addresses belonging to the attacker.

  • newdlocal() function: This is the main function that initiates the hijacking. It does two things:
    1. Overrides Network Requests: It monkey-patches the fetch API and XMLHttpRequest to intercept all incoming and outgoing HTTP requests. This allows it to inspect and modify the content of web pages.
    2. Address Scanning and Replacement: For every HTTP response, it calls the _0x19ca67 function, which in turn uses _0x20669a to scan the text for cryptocurrency addresses.
  • _0x20669a function: This is the heart of the address replacement logic.
    • It contains hardcoded arrays of attacker-owned cryptocurrency addresses for:
      • Bitcoin (BTC)
      • Bitcoin Cash (BCH)
      • Ethereum (ETH)
      • Litecoin (LTC)
      • Tron (TRX)
      • Solana (SOL)
    • It uses a set of regular expressions (_0x3ec3bb) to find potential crypto addresses in the text.
    • If a found address does not belong to the attacker's list, it replaces it with one that does. To make the replacement less obvious, it uses a Levenshtein distance algorithm (_0x3479c8 and _0x2abae0) to pick an address from its list that is visually similar to the original one.

This is the regex that tells us what the threat actors were targeting!

MetaMask Transaction Hijacking

The script has a special module, runmask(), dedicated to attacking users of the MetaMask browser wallet.

  • checkethereumw() and runmask(): The script first checks for the existence of window.ethereum, which is the object MetaMask injects into web pages. If found, it executes runmask().
  • Intercepting eth_sendTransaction: The runmask function wraps the window.ethereum.request method. This allows it to intercept all calls made to the user's wallet. When it detects a call to eth_sendTransaction, it modifies the transaction details before they are presented to the user for signing.
  • Malicious Transaction Modification (_0x1089ae function):
    • Redirecting ETH transfers: For a standard Ether transfer, it replaces the legitimate recipient's address (to) with the attacker's hardcoded address.
    • Stealing Tokens via approve: It looks for transaction data corresponding to a token approve call (identified by the function selector 0x095ea7b3). It then replaces the address that is being granted approval with the attacker's address, effectively giving the attacker the ability to drain all of that user's tokens.
    • Hijacking DEX Swaps: It identifies interactions with decentralized exchanges like Uniswap, PancakeSwap, and SushiSwap and modifies the transaction data to divert the swapped funds.

Lookalike NPM domains continue to deliver results for bad guys

The phishing email that started this mess came from the domain npmjs[.]help. This is the second or third time in recent months where simple lookalike domains have been used to successfully phish popular NPM maintainers. When is NPM going to get proactive and buy these domains ahead of time?

The domain was purchased and initially hosted on September 5th. The subdomains all used a single VPS server in the Netherlands:

More victims come to light

Unfortunately, several other NPM maintainers were also targeted in this attack, and have added additional information on a HackerNews post.

So far its unknown how many NPM maintainers got phishing emails, but we will update this blog post as we receive more information!

Let us know if this blog post helped you

Hit me up directly if you have any questions about this campaign.

Paul McCarty - Head of Research, Safety

You can find me on LinkedIn and BlueSky.

Related

Similar Posts

Secure your supply chain in 60 seconds.
No sales calls, no complex setup.
Just instant protection.

Get Started for Free
View Documentation
Arrow
CTA Graph