Threat Intelligence

Compromised npm Packages Reaching the Browser

Packages you legitimately depend on, compromised upstream, arriving in your bundle through the same pipeline everything else uses.

Published 31 March 2026
Updated 24 August 2026

Everything else we track gets onto a page by breaking in. This gets on by being invited: a package you chose, installed on purpose, built into your bundle by the pipeline that builds everything else.

The hosts here are exfiltration endpoints from separate incidents where a widely used npm package was taken over at the source and published with code added. One targeted wallet keys. Another was a compromise of one of the most downloaded HTTP clients in the ecosystem. A third was a template library whose earlier compromise had been cleaned up, then compromised again.

The account, not the code

These takeovers are rarely clever attacks on source code. They are attacks on the ability to publish: a phished maintainer, a stolen token, a stale credential in a CI configuration.

That matters for where you go looking. The public repository frequently still shows exactly the code you would expect, because the tampering happened between the source and the registry. Reading the GitHub page for a package tells you nothing about what npm actually served you.

What a lockfile does and does not do

A lockfile is a genuinely good control and it solves the adjacent problem. It stops your dependencies moving without you noticing, which rules out the version of this attack where a bad release arrives through an automatic upgrade.

It does nothing once the version you deliberately install is already compromised. Somebody bumps a dependency, CI is green, review passes, the lockfile records the choice — and then pins you to it with excellent reliability. Reproducibility is not integrity. A lockfile guarantees everyone builds the same thing, not that the thing is safe.

Subresource Integrity has a matching gap. It protects a script fetched from a URL against that file changing underneath the hash, which is exactly right for a CDN-hosted library. It cannot help with a package you installed and bundled, because the hash is computed over what you built, and what you built already contains the malicious code.

The one thing the attacker cannot avoid

Stolen data has to leave. Whatever the entry route, at some point code in the browser opens a connection to somewhere the attacker controls, and that destination has no business being in your policy.

That is why this is visible from the browser even when it is invisible everywhere else. Your build is reproducible, your dependencies are pinned, your repository is clean, and the page still tries to talk to a host nobody authorised.

What to look for

Watch for a connection to an unfamiliar host from a page whose own files did not change, and treat a new destination appearing shortly after a dependency bump as the two facts belonging together until shown otherwise.

The practical control is the same one that works against everything else here: a connect-src that names the origins your pages are allowed to reach, derived from what they legitimately need. It does not care how the code got onto the page, which is what makes it useful against a route that arrived through your own pipeline with a review and a green build behind it.

Indicators

The hosts we're tracking for this campaign

These are the entries in our threat intelligence feed for this campaign, shown exactly as we match them. An entry starting *. covers that domain and everything under it, so an attacker cycling through subdomains doesn't get away from it. We only do that when the attacker registered the domain themselves.

The feed changes as we go. We add hosts when they show up and pull them out when the evidence no longer holds, so this is what we're matching today rather than a permanent record.

cfww.shop
jiathis.com
l1ewsu3yjkqeroy.xyz
sfrclak.com
sol-rpc.xyz
utaq.cfww.shop
v3.jiathis.com

Corroborated by external research. We classify these on what we saw them doing, not on any claim about who runs them.

Disputing a classification →

FAQ

Frequently asked questions

Usually the publishing account rather than the code. Someone phishes a maintainer's credentials or steals a publish token and pushes a release under their name. The repository often still shows clean code, because the tampering happened between the source and the registry.

It stops you upgrading by accident, which is worth having. It does nothing once you deliberately take a version that is already malicious, and it will then pin you to that version very reliably.

A script loaded from a URL with a hash attached. If the file changes, the browser refuses it. That covers a CDN serving something new under an existing URL; it does not cover a version you installed and bundled yourself, because the hash is taken from what you built.

By the connection, not the code. The exfiltration has to reach somewhere, and that destination is not in your policy, so it is reported as a violation on the page the bundle runs on.

Find out if this is running on your site.

We flag these hosts in your own reports automatically, so you hear about it from us instead of from your customers.

← All threat intelligence research · Read this page as Markdown