148 npm Packages Disguised as Student Proxies Turned Browsers Into a DDoS Botnet
A campaign of 148 npm packages disguised as student web proxies turned visitors' browsers into a distributed denial-of-service botnet for roughly two weeks in May. These packages, initially designed as tutoring tools, loaded a remote code loader and a Wisp proxy protocol to facilitate a flood of traffic against a nursing school in Illinois, while also targeting other proxy servers. The operators quickly removed the malicious components, but the packages remain available on npm, and the threat actors retain the ability to re-enable the DDoS capability. Remediation involves blocking associated domains and clearing browser caches.
A campaign of 148 npm packages disguised as student web proxies turned visitors' browsers into a distributed denial-of-service botnet for roughly two weeks in May. These packages, initially designed as tutoring tools, loaded a remote code loader and a Wisp proxy protocol to facilitate a flood of traffic against a nursing school in Illinois, while also targeting other proxy servers. The operators quickly removed the malicious components, but the packages remain available on npm, and the threat actors retain the ability to re-enable the DDoS capability.
These packages did not target developers; instead, they were designed to be installed by students seeking to bypass school web filters. The operators used the npm registry as a free hosting platform and let students supply the attack traffic. The packages were named with juvenile terms like ‘charlie-kirk,’ ‘ilovefemboys,’ and ‘miguelphonk,’ and branded as ‘Lucide’ tutoring services.
Under the surface, the packages loaded a remote script loader, fetching JavaScript from a GitHub repository via the jsDelivr CDN, pointing to a mutable branch without Subresource Integrity checks, and running whatever came back with the proxy site's own origin privileges – full access to cookies, local storage, and same-origin endpoints. A no-referrer policy kept the request from advertising where it came from. The repository returned a 404 by the time JFrog looked, but an archived copy from May 30 preserved what it had served: a crude HTTP flood. Every 500 milliseconds, the script built a fresh one-million-character string and fired it as a no-cors POST at cdn.caan.edu, which JFrog identified as the public domain of a nursing school in Matteson, Illinois. The requests never waited for a response, so they stacked up, pushing around 2 GB per second at the target, and a randomized query parameter defeated caching proxies, and no-cors skipped the CORS preflight.
Alongside the HTTP flood, the packages also utilized a Wisp proxy protocol, loading a plain text file, ‘websocket.txt,’ holding a target WebSocket URL and a socket count capped between 1 and 1,024, then opening those many connections in a staggered loop. Each browser set its socket to binary mode and, every 100 milliseconds, sent a valid Wisp CONNECT frame followed by a CLOSE frame, both pointed at localhost:1. The frames were correct little-endian Wisp packets, so the target was not the student’s own machine, but a remote Wisp server on the far end of the connection.
This control-plane attack, rather than a volumetric one, allowed a single browser running 1,024 sockets to push about 10,240 connections a second while writing more than 20,000 log lines. The Wisp server, ‘wisp-server-node,’ opened a fresh socket for every CONNECT frame without checking whether the destination was a loopback or private address, and logged each attempt, exhausting file descriptors and flooding log storage.
JFrog traced the builds to a GitHub organization named ‘lucideproxy,’ whose accounts were registered seconds apart, tied to a commit email at ‘geeked[.]wtf’ and a Discord handle. Ninety of the 93 deployment hostnames it found resolved to one IP address, 92.38.177[.]17, hosted by G-Core Labs. The juvenile package names, an auto-publish shell script left inside the tarballs, and a “TY WAVES + CHATGPT ILY” comment SafeDep found in the service worker, all pointed to young operators. One account pushed 116 packages in under 35 minutes, and npm did nothing to slow it down.
JFrog’s commit history laid out the arc: the project started as plain adware in March, added the remote loader and the Wisp generator in a two-day burst in mid-May, ran the live flood against the nursing school at the end of the month, then stripped the malicious modules back out on May 31 as reporting started. A second wave on July 8, under a new account, brought the total to 148 packages and shipped the cleaned-up, adware-only build. The app is still obfuscated, still loads third-party scripts from attacker domains, and the loader still points at a mutable branch. The DDoS capability is not gone, only switched off.
Administrators on school and corporate networks, where these proxies pull the most traffic, should block the campaign’s domains at the DNS level. The monetization and script hosts the current build still reach, among them woofbeginner[.]com and c.vipersfutbol[.]com, are the ones to block first. Anyone who has loaded one of the proxy sites should clear the browser cache and local storage and unregister any service worker left behind by a tutoring or proxy domain. Teams whose build environments fetched the named packages should pull them from manifests and lockfiles and rebuild clean. JFrog’s write-up carries the full list of 148 packages, domains, IP addresses, and hashes.
