SecurityNot yet confirmed elsewhere1 publisher2 min readPublished
WSL is a working bridge, and npm hygiene stops at the container wall
CloudSEK's BRIDGEHEAD report tracks forty npm typosquats whose install script tests for Windows underneath Linux, then pulls a Rust stealer that reads the host's wallets and cookies.
The Watch · Security desk
What happened
- CloudSEK found forty npm packages published in August 2026, each a misspelling of chalk, axios, commander, lodash, react or typescript; all have since been removed.
- Their install script tests whether Windows sits under the Linux environment and, if so, downloads and runs a native Windows executable the package never shipped.
- That executable decodes and decrypts an embedded stage inside its own process, writing no file to disk and spawning no child process.
- Memory from the running stage held twenty-six desktop wallet paths, Chromium credential, cookie and history stores, and the Telegram Desktop session directory.
- The Rust payload, hosted as a GitHub release asset, kept serving for about 39 hours after the packages went away and logged 54 further downloads.
Why it matters
- constraint Dependency controls end at the container wall, so an npm-side programme can be working exactly as designed while none of it covers the wallets, cookies and messenger sessions actually in scope.
- exposure Any workstation where a Linux sandbox can start a Windows process has its host profile inside the blast radius of a single mistyped install command.
- decision Leaving WSL interop enabled on machines that also hold browser profiles and wallets becomes a policy call someone has to sign, not a default nobody looked at.
- precedent A payload that keeps serving after the packages advertising it are gone makes registry unpublishing the opening move of a response rather than its conclusion.
WSL's boundary is a convenience for the developer, not a control for the defender, and BRIDGEHEAD reads it that way. The courier does its work inside the Linux userland where the dependency landed: profile the host, report to a command and control server, then test for a Windows machine underneath [7]. The only feature the campaign needed from the registry was the install script, which all forty packages carried [6]. Registry allowlists, lockfiles, a private mirror, a review gate on new dependencies: all of that governs what gets into the userland, which is the side of the line with nothing on it worth stealing. The paths the stealer carries resolve into the Windows user profile, including Brave directories that did not exist on the analysis machine [16], and by the time CloudSEK captured guest memory it had already built a hardware profile of the box and staged the multipart header for the upload [17].
The takedown record is the part to take into a vendor conversation. According to CloudSEK the two halves of the campaign had opposite lifespans: the npm layer cheap and disposable, the payload layer one GitHub release asset plus a route out through a public file host, and the unpublishing touched neither [5]. Across the window observed on 17 August the asset was being pulled at roughly 3.2 times an hour with no live package left to advertise it [19]. It stopped being available when the bebraz1 account itself returned 404, four hours after the last reading and only because analysts were watching [10]. CloudSEK's own summary is that the npm takedown left the weapon in place [4].
The file is also a lesson in what size tells you. 265 kilobytes of the 22 megabyte binary is code, and 98.6 per cent of it is one unbroken run of 22,638,592 hexadecimal characters [11], which decode to 11,319,296 bytes of encrypted stage [20]. A Rust executable that is roughly one per cent program and the rest a hex string is an anomaly a build or download pipeline could measure by arithmetic alone, and it is close to the only static signal on offer, because the runtime behaviour is designed to produce none [12]. The upload lands on gofile.io, which CloudSEK points out is a legitimate service and cannot be seized the way a criminal domain can [14].
One caveat on sourcing: this is CloudSEK's investigation, published 20 August 2026 [18], and the packages are already gone [1], so the forty-name list is no longer checkable against the live registry.
What to watch
- Whether the same release asset reappears under a new GitHub account, which would show the durable layer is being reprovisioned rather than retired.
- Whether npm or GitHub begin flagging install scripts that branch on WSL or Windows detection, the one behaviour the campaign depended on.
- Independent confirmation of the forty-package list and the gofile.io exfiltration route, since CloudSEK is so far the only party reporting them.
Clarity's read
What the record supports and how the coverage leans. The claims behind it follow.
Reality
- Evidence63
- Adoption27
- Hype gap+14
- Incentives74
- Confidence56
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
In August 2026 an operator published forty packages to the public npm registry, each a misspelling of a heavily installed library: chalk, axios, commander, lodash, react and typescript. The packages have since been removed.
ReportedSupportedSource: CloudSEK BRIDGEHEAD report2 sources— create a free account to open themView cited source - [2]
The GitHub payload outlived the npm packages by roughly 39 hours.
- [3]
The payload's download counter was observed rising from 119 at 01:50 UTC on 17 August to 173 by 18:49 UTC the same day, 54 pulls, after the packages that pointed at it had ceased to exist.
- [4]
CloudSEK states that the npm takedown, on its own, left the weapon in place.
- [5]
CloudSEK describes the campaign as two layers with opposite lifespans: a loud, cheap, disposable npm layer of forty impersonation packages, and a quiet, durable payload layer of one Rust executable on GitHub plus one exfiltration route through a public file host, neither of which the npm takedown affected.
- [6]
Every one of the forty npm packages carried an install script.
- [7]
The install script profiles the host, reports to a command-and-control server, and then checks whether the machine is Windows or a Windows Subsystem for Linux environment sitting on top of Windows.
- [8]
If the host is Windows or WSL, the script decodes a hidden instruction and reaches across the boundary separating a developer's Linux shell from the Windows host underneath, downloading and running a native Windows executable that the npm package never contained.
- [9]
The downloaded executable is a 22 megabyte Windows program written in Rust, hosted as a release asset on GitHub rather than on npm.
- [10]
The payload was removed only during CloudSEK's analysis: the entire bebraz1 account returned 404 within four hours of that last download-counter reading.
- [11]
The executable code in the 22 megabyte file is 265 kilobytes, roughly one per cent; the other 98.6 per cent is a single unbroken run of 22,638,592 hexadecimal characters holding an 11 megabyte encrypted payload written out as text.
- [12]
main.exe decodes the hex text back to bytes, decrypts it and runs the result inside its own process; nothing is written to disk and no second process is created, so an endpoint looking for a dropped file or an unusual child process sees neither.
- [13]
Detonated in an isolated Windows environment, the payload fingerprints the victim's public IP address and then attempts to upload to gofile.io, an anonymous public file-sharing service, instead of beaconing to attacker infrastructure for exfiltration.
- [14]
CloudSEK notes that gofile.io is a legitimate service that cannot be taken down as though it were a criminal domain.
- [15]
Memory capture of the running payload recovered three target lists, already expanded for the victim's account, covering twenty-six desktop cryptocurrency wallet paths, the credential, cookie and history stores of Chromium-family browsers, and the session directory of Telegram Desktop.
- [16]
The recovered target lists include paths for Brave installations that did not exist on the analysis machine, which CloudSEK reads as the signature of a hardcoded target list.
- [17]
At the time of memory capture the payload had already assembled a hardware profile of the machine and the multipart header of the upload.
- [18]
The BRIDGEHEAD report is published by CloudSEK and dated 20 August 2026.
- [19]
The observed download window runs 16 hours 59 minutes, giving an average of about 3.2 pulls per hour while no npm package pointing at the asset existed.
- [20]
The 22,638,592 hexadecimal characters embedded in the binary decode to 11,319,296 bytes of encrypted stage.
Sources
1 independent publisher whose own reporting we read for this story.
- BRIDGEHEAD : An npm typosquatting campaign that crosses from WSL into Windows to plant a crypto-wallet stealer | CloudSEK
cloudsek.com
1 article · August 26, 2026
Topics and entities
Follow any of these and your For You feed starts watching them — no settings page required.
Topics
- Infostealer MalwareFollow
- Software Supply Chain SecurityFollow
- In-memory execution and detection evasionFollow
- WSL-to-Windows boundary crossingFollow
- npm typosquatting and namespace squattingFollow
- Takedown scope and abuse of legitimate infrastructureFollow