Skip to main content
Emerging ThreatsMalware & Ransomware

npm Packages Turned into DDoS Botnet via Student Proxies

Laptops scattered in a brightly-lit university setting, hinting at cyber threat.

148 npm packages masquerading as student web proxies turned browsers into a distributed denial-of-service botnet for roughly two weeks in May, according to new research from JFrog.

Lucide-themed packages and student proxies

JFrog found more than a hundred packages published to the npm registry that presented a benign student proxy and tutoring landing page — branded in the UI as “Lucide” and wrapped as Riverbend Tutoring or Northstar Tutoring — but carried hidden attack code beneath a surface of ads and monetization scripts. Package names included charlie-kirk, ilovefemboys, and miguelphonk. SafeDep cataloged 141 of the packages in May as registry abuse and adware; JFrog extended that list to 148 after a second publish wave on July 8.

G2: the remote loader and the HTTP flood

JFrog deobfuscated the app entry bundle — a single 5.4 MB line of JavaScript that expanded to more than 20,600 lines — and identified two modules that run before the React interface renders. The first, labeled G2, is a remote script loader. It pulled JavaScript from a GitHub repository via the jsDelivr CDN, pointing at the mutable main branch rather than a pinned commit, shipped no Subresource Integrity checks, and executed returned code with the proxy site’s origin privileges. A no-referrer policy hid the request source.

An archived copy from May 30 preserved the G2 payload: every 500 milliseconds the script constructed a one‑million‑character string and sent it as a no-cors POST to cdn.caan.edu — identified by JFrog as the public domain of a nursing school in Matteson, Illinois. Because requests never wait for a response and include randomized query parameters to defeat caching, JFrog estimated roughly 2 MB per second of upload per active visitor; a thousand open pages could push about 2 GB/s at the target.

I2: the Wisp WebSocket control-plane assault

The second module, I2, read a plain-text websocket.txt that contained a target WebSocket URL and a socket-count (capped between 1 and 1,024), then opened that many staggered connections. An archived configuration aimed each browser at 30 connections to a Wisp endpoint on lunaron[.]top. Wisp, described by JFrog as a Mercury Workshop protocol, tunnels TCP and UDP sockets over a WebSocket and is common in the browser-proxy scene.

Once connected, each browser set sockets to binary mode and, every 100 milliseconds, sent a correct little-endian Wisp CONNECT frame followed by a CLOSE frame pointed at localhost:1. Because wisp-server-node (the server implementation targeted) opens a fresh socket for every CONNECT without checking whether the destination is loopback or private — and logs each attempt — JFrog shows a single browser running 1,024 sockets can force the server to allocate and tear down about 10,240 connections per second while producing more than 20,000 log lines, quickly exhausting file descriptors, flooding logs, and dropping the proxy. JFrog notes wisp-server-node is deprecated and its maintainers have warned of exactly this class of problem.

Infrastructure, operational signals, and timeline

JFrog traced the builds to a GitHub organization named lucideproxy; accounts were registered seconds apart and tied to a commit email at geeked[.]wtf and a Discord handle. Ninety of 93 deployment hostnames resolved to a single IP, 92.38.177[.]17, hosted by G-Core Labs. Operational artifacts — juvenile package names, an auto-publish shell script left inside tarballs, and a “TY WAVES + CHATGPT ILY” comment SafeDep found in a service worker — led both firms to read the operator as young. One account pushed 116 packages in under 35 minutes, and npm did not throttle publishing.

JFrog’s chronology: the project began as plain adware in March, added the remote loader and Wisp generator in a two-day burst in mid-May, ran the live HTTP flood against the nursing school at the end of May, then removed the malicious modules on May 31 as reporting began. A July 8 second wave, published under a new account, increased the package count to 148 but shipped a cleaned-up, adware-only build. JFrog warns the loader still points at a mutable branch and can be re-armed with a single commit. On July 14, 2026, a spot check by The Hacker News found most packages removed from npm, but charlie-kirk still served the two versions JFrog flagged as malicious, 2.0.0 and 3.0.1.

What this means for school and corporate networks, and for open-source maintainers

  • School and corporate network administrators: block the campaign’s domains at DNS. JFrog lists monetization and script hosts still contacted by the current builds — among them woofbeginner[.]com and c.vipersfutbol[.]com — as primary blocks to apply.
  • End users and IT teams that encountered a proxy site: clear browser cache and local storage and unregister any service worker left behind by a tutoring or proxy domain.
  • Build and dependency teams: remove the named packages from manifests and lockfiles and rebuild clean. JFrog’s write-up includes the full list of 148 package names, domains, IPs, and hashes for those managing dependency hygiene.

Remediation status and an open operational question

Many packages have been pulled from npm and replaced with the registry’s standard 0.0.1-security placeholder. JFrog and SafeDep documented the code, and The Hacker News has reached out to JFrog for further details on the botnet’s scale and whether the WebSocket attack ran against a live proxy target. JFrog’s analysis underscores a practical consequence: when public registries double as free CDNs and client-side web apps are delivered through npm packages that never run at install-time, the packages most dangerous to operations may be the ones no build pipeline ever pulls.

Original story