{"id":1365,"date":"2026-10-19T07:00:00","date_gmt":"2026-10-19T07:00:00","guid":{"rendered":"https:\/\/allcloudhost.net\/blogs\/?p=1365"},"modified":"2026-10-08T04:22:05","modified_gmt":"2026-10-08T04:22:05","slug":"baileys-malicious-npm-whatsapp-packages","status":"publish","type":"post","link":"https:\/\/allcloudhost.net\/blogs\/baileys-malicious-npm-whatsapp-packages\/","title":{"rendered":"101 Fake Baileys Forks Hijacked WhatsApp Sessions on npm Install Alone: What to Actually Check"},"content":{"rendered":"<h2 class=\"wp-block-heading\" id=\"h-a-normal-npm-install-was-the-entire-attack\">A Normal npm Install Was the Entire Attack<\/h2>\n<p>A campaign researchers are calling PhantomSub placed 101 malicious packages on npm, collectively downloaded around 490,000 times, with 116,000 of those downloads in just the last 30 days before discovery. Every one of them posed as a fork or variant of Baileys, a legitimate, widely used open-source library for building WhatsApp bots. Names like ourin-baileys, @nexustechpro\/baileys, levvleys, neuralwhatsapp, cloud-baileys, and my-auto-follow were built to read as plausible forks or alternative implementations rather than obvious typosquats, the kind of name a developer searching npm for &#8220;baileys alternative&#8221; or &#8220;baileys fork&#8221; might reasonably click on.<\/p>\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\">\n<h2>Table of Contents<\/h2>\n<nav>\n<ul>\n<li><a href=\"#h-a-normal-npm-install-was-the-entire-attack\">A Normal npm Install Was the Entire Attack<\/a><\/li>\n<li><a href=\"#h-a-campaign-that-ran-for-a-while-before-anyone-noticed\">A Campaign That Ran for a While Before Anyone Noticed<\/a><\/li>\n<li><a href=\"#h-three-baileys-variants-three-different-levels-of-effort-to-d\">Three Baileys Variants, Three Different Levels of Effort to Detect<\/a><\/li>\n<li><a href=\"#h-why-it-s-a-popular-library-s-fork-isn-t-a-safety-signal\">Why &#8216;It&#8217;s a Popular Library&#8217;s Fork&#8217; Isn&#8217;t a Safety Signal<\/a><\/li>\n<li><a href=\"#h-what-to-check-if-you-ve-already-installed-something-from-thi\">What to Check If You&#8217;ve Already Installed Something From This List<\/a><\/li>\n<li><a href=\"#h-why-this-specifically-targeted-a-messaging-library-not-a-gen\">Why This Specifically Targeted a Messaging Library, Not a Generic Utility<\/a><\/li>\n<li><a href=\"#h-building-this-into-how-you-install-dependencies-going-forwar\">Building This Into How You Install Dependencies Going Forward<\/a><\/li>\n<\/ul>\n<\/nav>\n<\/div>\n<p>What makes this campaign worth understanding in detail rather than just noting as &#8220;another bad npm package&#8221; story: the malicious behavior activated during a routine install, with no further action required from the developer. Once a project authenticated its own WhatsApp bot session through one of these packages, that session got silently used to add the developer&#8217;s WhatsApp account to attacker-controlled groups and channels, mostly advertising bot-building services, in-game currency, and mobile game accounts, concentrated on Indonesian markets based on the channels researchers identified.<\/p>\n<h2 class=\"wp-block-heading\" id=\"h-a-campaign-that-ran-for-a-while-before-anyone-noticed\">A Campaign That Ran for a While Before Anyone Noticed<\/h2>\n<p>The download numbers tell their own story about detection speed. If 116,000 of the roughly 490,000 total downloads happened in just the most recent 30 days, the remaining 374,000, over three-quarters of the total, accumulated before that final month, meaning this collection of packages was quietly installing itself into projects for a sustained period before the campaign was identified and reported. That&#8217;s consistent with how supply-chain attacks on package registries tend to play out: there&#8217;s no equivalent of a antivirus definition update that catches a brand-new malicious package on day one, so a campaign built around plausible-looking fork names can accumulate a real install base before anyone specifically goes looking for it.<\/p>\n<h2 class=\"wp-block-heading\" id=\"h-three-baileys-variants-three-different-levels-of-effort-to-d\">Three Baileys Variants, Three Different Levels of Effort to Detect<\/h2>\n<p>The researchers broke 93 of the 101 packages into three technical approaches, and the differences matter for anyone thinking about how a scanner would or wouldn&#8217;t have caught this. Nineteen packages fetched their target channel IDs from GitHub at runtime, meaning the malicious destination wasn&#8217;t even fixed in the package code itself, just a pointer to wherever the attacker&#8217;s GitHub repo said to go that day. Sixty packages, the majority, embedded the channel IDs directly in plaintext source, the easiest variant for a static scanner or a manual code read to catch, since the actual malicious string is sitting in the open.<\/p>\n<p>Fourteen used encoded and obfuscated embedded IDs, splitting the difference: no runtime fetch to flag as suspicious network activity, but also not a plaintext string a simple grep would catch.<\/p>\n<p>That spread is a useful reminder that &#8220;I scanned the package and didn&#8217;t see anything obviously wrong&#8221; isn&#8217;t a uniform guarantee across all three approaches. A plaintext scan catches the 60-package majority easily, but the runtime-fetch and obfuscated variants need a closer look at what the package actually does at install or run time, not just what strings are visible in its source.<\/p>\n<h2 class=\"wp-block-heading\" id=\"h-why-it-s-a-popular-library-s-fork-isn-t-a-safety-signal\">Why &#8216;It&#8217;s a Popular Library&#8217;s Fork&#8217; Isn&#8217;t a Safety Signal<\/h2>\n<p>The core lesson generic to any package that presents itself as an alternative or fork of something legitimate: the fact that a project is a fork of a well-known, trusted library tells you nothing about whether the fork itself is trustworthy. A fork can be a completely independent codebase with a new maintainer and no actual code-level relationship to the original beyond the name and README positioning.<\/p>\n<p>Before installing anything presenting itself this way, a few concrete checks take less time than dealing with the aftermath: run <code>npm view &lt;package-name&gt;<\/code> and check who actually published it and when, compare that against the real upstream project&#8217;s own GitHub repository activity (does the claimed fork actually show up as a fork or contributor there, or does it only claim the relationship in its own README), and check whether the package has any npm provenance attestation (packages published with provenance show a verified build-and-publish pipeline tied to a specific public source repository, which a hastily-published malicious fork typically doesn&#8217;t bother setting up).<\/p>\n<h2 class=\"wp-block-heading\" id=\"h-what-to-check-if-you-ve-already-installed-something-from-thi\">What to Check If You&#8217;ve Already Installed Something From This List<\/h2>\n<p>If a project on your own server has installed any package built around Baileys or presenting itself as a WhatsApp bot library, it&#8217;s worth specifically checking the WhatsApp account or number that bot session is tied to for group or channel memberships that weren&#8217;t deliberately joined, since that&#8217;s the actual, visible symptom of this specific campaign. Removing the package and rotating the bot&#8217;s session credentials afterward is the direct fix; simply leaving unwanted group memberships in place doesn&#8217;t undo whatever access the attacker&#8217;s package already had during the time it was installed.<\/p>\n<h2 class=\"wp-block-heading\" id=\"h-why-this-specifically-targeted-a-messaging-library-not-a-gen\">Why This Specifically Targeted a Messaging Library, Not a Generic Utility<\/h2>\n<p>It&#8217;s worth noting why WhatsApp-automation libraries make an attractive target for this kind of campaign specifically, rather than it being an arbitrary category to typosquat. A package that legitimately needs to authenticate a real messaging session is already asking a developer to trust it with exactly the kind of access, session tokens tied to a real personal or business account, that has direct value to an attacker, and that a developer installing it has already mentally approved as a reasonable thing for the package to need.<\/p>\n<p>That built-in trust is what made a malicious fork&#8217;s authentication request look unremarkable rather than suspicious, the same request a legitimate Baileys install would also make. Packages in categories that inherently require sensitive authentication (messaging, payment, cloud-account automation) deserve a correspondingly higher bar for verifying the maintainer before installing, compared to a package that&#8217;s just doing string formatting or date parsing with no real access to anything sensitive.<\/p>\n<h2 class=\"wp-block-heading\" id=\"h-building-this-into-how-you-install-dependencies-going-forwar\">Building This Into How You Install Dependencies Going Forward<\/h2>\n<p>On a self-managed VPS or dedicated server, where you have full root access and nobody else is vetting what gets installed, dependency hygiene is entirely on the account holder. A lockfile (package-lock.json or equivalent) pinned to specific, already-reviewed versions prevents an automatic minor-version bump from silently pulling in a compromised update to a package that was clean when first installed. Running <code>npm audit<\/code> regularly catches known-bad packages already reported to npm&#8217;s advisory database, though it won&#8217;t catch a brand-new campaign before it&#8217;s been flagged, which is exactly the window this campaign operated in before discovery.<\/p>\n<p>For any project handling something as sensitive as an authenticated messaging session, treating a &#8220;fork&#8221; or &#8220;alternative&#8221; of the real library with the same scrutiny as an unfamiliar package entirely, rather than borrowed trust from the original project&#8217;s reputation, is the one habit that would have stopped this specific campaign at the install step, before any of the 490,000 downloads ever ran.<\/p>\n<p>Related reading: <a href=\"https:\/\/allcloudhost.net\/blogs\/malicious-npm-package-twilio-bug-bounty\/\">A Malicious npm Package Posed as a Twilio Bug-Bounty Tool. Here&#8217;s What Developers Should Check<\/a> and <a href=\"https:\/\/allcloudhost.net\/blogs\/npm-supply-chain-attack-redc2-linux-backdoor\/\">14 Trojanized npm Packages Are Dropping a Linux Backdoor<\/a>.<\/p>\n<p>Further reading: <a href=\"https:\/\/docs.npmjs.com\/cli\/v10\/commands\/npm-audit\" target=\"_blank\" rel=\"noopener\">npm Docs: npm audit<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A Normal npm Install Was the Entire Attack A campaign researchers are calling PhantomSub placed 101 malicious packages on npm, collectively downloaded\u2026<\/p>\n","protected":false},"author":2,"featured_media":1364,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":0,"rank_math_title":"Baileys npm Packages: 101 Fakes Hijacked WhatsApp Sessions","rank_math_description":"101 fake Baileys forks on npm hijacked WhatsApp sessions at install. How the PhantomSub campaign worked and how to vet a package before adding it.","rank_math_focus_keyword":"baileys, malicious npm packages whatsapp, baileys npm security, npm supply chain attack","rank_math_canonical_url":"","rank_math_robots":[],"footnotes":""},"categories":[10],"tags":[],"class_list":["post-1365","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security"],"_links":{"self":[{"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/posts\/1365","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/comments?post=1365"}],"version-history":[{"count":4,"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/posts\/1365\/revisions"}],"predecessor-version":[{"id":1778,"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/posts\/1365\/revisions\/1778"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/media\/1364"}],"wp:attachment":[{"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/media?parent=1365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/categories?post=1365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/allcloudhost.net\/blogs\/wp-json\/wp\/v2\/tags?post=1365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}