An automated npm campaign uses hundreds of disposable packages to launch detached native malware, with DNS TXT records as a fallback delivery channel.2026-08-07T21:55:00.000Z7 min2026appsecendpointthreats
7 min read
Read format

Flooding Dropper Used 846 npm Components as Cross-Platform Loaders

An automated npm campaign uses hundreds of disposable packages to launch detached native malware, with DNS TXT records as a fallback delivery channel.

By Justin Howe
One large open software parcel reveals a violet-black loader core while three translucent signal paths leave the frame.

An active cross-platform malware campaign implicated 846 npm components in a disposable-package delivery system. Sonatype says, “The first-stage JavaScript acts as a cross-platform loader with several delivery paths.” OpenSourceMalware separately reported more than 700 packages published over 48 hours, measuring the campaign’s burst rather than Sonatype’s later affected-component record. This article uses Sonatype’s 846 count for scoping because it is tied to the searchable sonatype-2026-005660 component list.

Development teams should scope workstations, CI runners, caches, internal mirrors, test systems, and production-adjacent hosts against that list.

Nulltap’s recent report on an 18-package npm RAT chain examined one coordinated dependency chain. Flooding Dropper instead uses hundreds of disposable components, starts when affected code is imported, and retains a DNS delivery route when HTTPS fails.

The important trigger is not limited to installation. OpenSourceMalware found that importing an affected module with require() can start the downloader. It tries HTTPS, falls back to payload chunks carried in DNS TXT records, writes a native executable for Windows, macOS, or Linux, and launches that process detached. If the native stage ran or established persistence, removing the dependency does not terminate that process or remove those artifacts.

Package volume hides repeated behavior

The campaign uses many apparently random accounts that publish only a few packages each. Names have included combinations containing bigops and bnpl, and many versions have followed a 35.x.y pattern. Sonatype also saw new naming variants. Those strings help with immediate scoping, but they are not stable security boundaries.

Across samples, variable names and URL-building code change while the behavior stays substantially the same. The loader checks environment variables and a local marker, identifies the operating system and processor architecture, selects a compatible payload, and randomizes its delivery attempt. That variation can frustrate exact source signatures without materially changing the chain.

OpenSourceMalware’s worked example was [email protected], which exposed a harmless-looking SDK interface. Beneath its export, a helper loaded and ran automatically. The package did not need a preinstall or postinstall script, which means controls that disable npm lifecycle scripts do not close the exposure when application or test code later imports the dependency.

The Flooding Dropper chain from package import through HTTPS or DNS TXT delivery to a detached native payload.

Figure details

An affected npm package can execute when imported. The loader fingerprints the host and first tries three Cloudflare Workers HTTPS endpoints. If those attempts fail, it queries a count record and numbered DNS TXT records under platform-specific wel1.ru subdomains, joins and Base64-decodes the chunks, then writes a platform-specific executable. If that native stage launches, it can continue independently of npm or Node.js. The Windows and macOS stages analyzed by the researchers can establish persistence or load further stages.

DNS provides a second delivery route

The first stage rotates through oob-worker.cf103-070.workers[.]dev, oob-worker.cf102-baf.workers[.]dev, and oob-worker.cf99-9b3.workers[.]dev with the user agent node-fetch/2.6. Its platform paths are /pkg/package, /pkg/package-arm64, /pkg/loader_mac, and /pkg/package.exe. If those HTTPS attempts fail, the loader selects sdk.dl.wel1[.]ru, ext.dl.wel1[.]ru, pkg.dl.wel1[.]ru, or net.dl.wel1[.]ru according to the host platform.

The fallback is explicit. It first requests c.<domain> to obtain a chunk count. It then queries numbered names such as 0.sdk.dl.wel1[.]ru, joins the returned TXT strings, and Base64-decodes them into a binary buffer. Blocking the three web hosts therefore does not stop a host whose DNS resolver can still reach the fallback domains.

On Unix-like systems, the loader runs /bin/sh -c "/var/tmp/.cache_<id> &". On Windows, the equivalent pattern is cmd.exe /c start /b %TEMP%\dotnet_diag_<id>.exe. Both paths detach the child and suppress its input and output. The exact repeat-execution markers are /tmp/.analytics_state and %TEMP%\analytics_state; the analytics name is camouflage, not evidence of legitimate telemetry.

Native stages survive the package process

Sonatype observed a Windows stage that patches Event Tracing for Windows and Antimalware Scan Interface functions, checks for debuggers, virtual machines, sandboxes, and security products, then copies itself into a persistent user location. That analyzed stage used both a Registry Run key and a scheduled task. It could retrieve an encrypted payload from /pkg/update_win.exe, decrypt it, and execute it reflectively in memory.

OpenSourceMalware documented macOS persistence through ~/.local/share/runtime/.lock, ~/.local/share/runtime/com.apple.runtime, and a LaunchAgent at ~/Library/LaunchAgents/com.apple.windowserver.helper.plist. The analyzed loader activates that LaunchAgent with launchctl load -w '<path>/com.apple.windowserver.helper.plist' 2>/dev/null. The names imitate ordinary platform components but are not legitimate in those locations.

The analysis paired the Linux sample filename oob-worker.cf103-070.workers.dev.linux-second-stage.payload with SHA-256 7e486657f30594afda379b97030252a09a19fe8055e25c9e371544f59bd8e9e3. It paired the macOS sample filename oob-worker.cf99-9b3.workers.dev.second.stage.payload with SHA-256 c214746c74cae8ece8bdaf69aa05da4db6ce013f9e77452d1eed1a002fd9ba00.

Later-stage evidence includes /pkg/beacon_mac.bin and the Workers hosts package-proxy[.]cf11oobworker.workers[.]dev, package-proxy[.]cf5oobworker.workers[.]dev, package-proxy[.]cf6oobworker.workers[.]dev, package-proxy[.]cf7oobworker.workers[.]dev, and package-proxy[.]cf8oobworker.workers[.]dev. Another DNS route uses dl[.]wel1.ru, with count queries such as c.<session-or-host-id>.dl[.]wel1.ru followed by numbered TXT requests such as 0.<session-or-host-id>.dl[.]wel1.ru.

The macOS sample also contains the health-check paths https://nexus[.]tcsbank[.]ru/health, https://repo-linux[.]tcsbank[.]ru/health, https://alertmanager[.]cloudpayments[.]ru/health, and 127.0.0.1:4444/health. The loopback address is not an external indicator. The three public domains are investigation leads, and the source does not establish that each one is attacker-controlled command infrastructure.

The Linux sample downloaded another stage from the campaign infrastructure. A separate researcher described that last stage as Sliver, but OpenSourceMalware had not independently confirmed that identification when it published. That uncertainty does not change the containment decision: execution already crosses from package code into an untrusted native process.

Embedded references to Russian financial institutions and use of a .ru delivery domain may indicate target interests or infrastructure choices. They do not establish the operator’s nationality or identity. Neither primary analysis reports a victim count. Neither reports a package-registry vendor response or a package-removal count.

Hunt dependencies and endpoint behavior

Start with Sonatype’s current sonatype-2026-005660 component list, then search lockfiles, package-manager logs, npm caches, software-composition records, container layers, internal mirrors, build artifacts, and CI job history. The sources provide no fixed clean package version or build. The current component list supersedes static package-name and 35.x.y pattern checks as the campaign changes. Check both direct and transitive resolution. A clean present-day package.json does not prove that a removed version never executed.

Correlate dependency evidence with DNS, proxy, process, and endpoint telemetry. Look for the three published Workers hosts; TXT queries to the platform-specific wel1[.]ru names; Node.js or npm ancestry followed by /bin/sh or cmd.exe; detached executables from temporary directories; .analytics_state; the macOS runtime directory and LaunchAgent; /pkg/update_win.exe; the four published health-check paths; and unfamiliar Run keys or scheduled tasks created near package activity.

Package names, accounts, and IP addresses will rotate. Behavioral detections should therefore preserve the relationship: a development or build process imports a new dependency, contacts campaign delivery infrastructure or performs numbered TXT queries, writes a native file into a temporary location, and spawns it detached.

Contain hosts before rotating secrets

Package removal cannot settle host state.

The package record answers where the campaign entered a dependency graph. It does not answer whether the native stage ran, whether persistence survived package cleanup, or which credentials were available to the process. That is why this campaign stops being a dependency-maintenance problem once import-time execution is plausible.

The sources do not report installs, victims, or compromised organizations. That missing scale should prevent inflated impact claims, but it does not make package removal an adequate endpoint. The moment the loader may have spawned a detached executable, host state and account history become the evidence that determines the response.

Separate package, host, and credentials

Each scope needs its own evidence.

Search Sonatype’s current sonatype-2026-005660 list across repositories, lockfiles, caches, mirrors, container layers, developer systems, and CI runners. Remove affected components and confirm controls prevent direct or transitive return.

For hosts that may have imported an affected package, follow Sonatype’s order: isolate the system; investigate Node.js or npm process ancestry, numbered TXT lookups, the published Workers domains, .analytics_state, temporary executables, macOS LaunchAgent state, Windows Run keys, scheduled tasks, and credential use history; remove persistence and eradicate or rebuild the host as appropriate; then rotate npm, GitHub, cloud, CI/CD, and other developer credentials after remediation. Treat executed packages as host compromise until that path is bounded.

The expected result is no unexplained native child, persistence artifact, or credential use tied to an affected package import.

The package list maps the campaign; host behavior decides the damage. A repository can be clean while a developer laptop still carries the loader’s consequences, and a rotated token can still have an unexplained release or session behind it. This campaign turns dependency hygiene into incident response the moment code execution is plausible.

Primary sources

Continue reading

Article figurePinch or double-tap to zoom, then drag to pan.