OX Security published research on 28 September 2026 on a campaign it calls PhantomSub: 101 npm packages, downloaded about 490,000 times in total and 116,000 times in the previous thirty days, that quietly enrol the developer's own WhatsApp account into channels somebody else owns.
Sixteen of the packages had been removed from npm when the research went out. The rest were still installable.
What the packages actually do
All of them wrap Baileys, a widely used open-source library for talking to WhatsApp from Node.js. Linking an account to a Baileys project is ordinary: you scan a code, the library holds a session, and your script can send and receive messages.
The malicious packages add one step at that moment. Once the account is authenticated, the code subscribes it to a list of channels or groups the operator controls, and in some cases mutes them, so the developer gets no notification and sees nothing move in their chat list.
OX describes three variants, which differ only in where the channel list lives:
- 19 packages fetch the list from GitHub while running, so the operator can change the targets later.
- 60 packages carry the identifiers in plain text in the source.
- 14 packages carry them encoded, which defeats a grep and not much else.
The payload is an audience
Nothing is stolen. No token leaves the machine, no file is read, no second stage is downloaded. What the operation produces is subscriber counts.
The channels OX looked at advertise bot-selling services, premium APK files, social-media boosting and game accounts, with one traced to an Indonesian operator and promoting TikTok accounts and Mobile Legends accounts. Subscriber numbers are the proof of reach that those listings are sold on, and a developer's authenticated WhatsApp account is a real account with a real phone number behind it.
That is what makes this hard to see. Supply-chain detection looks for the behaviour of theft: credential files, outbound posts of environment variables, obfuscated second stages. A package that adds a subscription triggers none of it, and the victim has no reason to look at their own channel list.
Why the account matters more than the machine
The thing compromised here is not the build server. It is the developer's personal messaging account, and it keeps the subscription after the package is uninstalled.
That also makes the clean-up unfamiliar. Removing the dependency and rotating the npm token does nothing: the account is still in the channel, the operator still counts it, and if the account is used for work, so is whatever that channel later sends.
OX names a WhatsApp business account operating from Indonesia, and GitHub accounts that host the remote channel lists. It does not claim that every package shares one author, and says so.
What 490,000 downloads is and is not
The download count is the number that will travel, and it is the softest figure here.
An npm download is a fetch, not an installation by a person. Continuous integration pipelines re-fetch dependencies on every run, mirrors and caches pull packages wholesale, and security scanners download to inspect. A single project wired into a busy pipeline can account for thousands on its own.
What the campaign needs is narrower than a download. It needs a developer to install one of these wrappers, then link a real WhatsApp account to it by scanning the code. Everything before that step costs the operator nothing and gains them nothing.
So the honest reading is that 490,000 is the reach of the distribution and not the size of the harm, and that the harm is bounded by how many people actually authenticated. Nobody has published that number, including OX.
The removal rate points the same way. Sixteen packages were gone when the research was published and eighty-five were not, which is the normal shape of registry take-downs: reports are handled package by package, and a campaign that publishes a hundred names survives the first round by arithmetic.
What to do
- Open WhatsApp on any phone that has been linked to a Baileys project and review the channels and groups it follows, including muted ones. Leave anything you did not join.
- Audit for Baileys wrappers in your dependency tree, especially packages that ask for a personal account to be linked at all.
- Treat a package that needs a personal messaging account as a different class of risk from one that needs an API key. A key can be revoked; an account you authenticated stays authenticated.
- Add the published channel identifiers and the remote list URLs to whatever blocklist your organisation keeps, if you run anything on WhatsApp at scale.
- Use a dedicated number for automation. A developer's own number should not be the one being enrolled.
What is not established
- Whether the packages share a single operator. OX draws no firm link between the publishers.
- Whether the channels are run by one group or are a service sold to many.
- How many of the 490,000 downloads resulted in an account being linked, which is the only step that matters.
- Whether npm has removed the remaining packages since the research was published.