On May 19, 2026, a threat actor tracked as TeamPCP compromised the npm account "atool" (email i@hust.cc) and used it to publish 639 malicious versions across 323 packages in the @antv data visualization ecosystem and its downstream dependents. The two publish waves, timestamped 01:56 UTC and 02:06 UTC, hit widely used libraries including @antv/g2, @antv/g6, @antv/x6, @antv/l7, @antv/s2, @antv/f2, echarts-for-react, timeago.js, and size-sensor — a set of packages with a combined footprint of roughly 16 million weekly downloads. Each poisoned version shipped a 486-498 KB obfuscated JavaScript payload that ran automatically on install via a preinstall hook, scraped CI/CD credentials, and exfiltrated them through a channel disguised as OpenTelemetry telemetry. Security researchers have branded this incident "Mini Shai-Hulud" because it reuses the self-propagating, credential-harvesting playbook of the September 2025 Shai-Hulud npm worm, but with a faster, more targeted execution model aimed squarely at build pipelines.
What Happened in the AntV npm Supply Chain Attack?
A single compromised maintainer account was used to publish 639 malicious versions of 323 packages in the @antv ecosystem within a roughly 10-minute window on May 19, 2026. The attacker gained control of the npm account "atool," which had publish rights across dozens of @antv namespace packages plus several popular standalone libraries that depend on them, including echarts-for-react and timeago.js. Because @antv/g2, @antv/g6, and @antv/x6 sit deep in the dependency trees of countless dashboards, admin panels, and data-visualization frontends, the blast radius extended well beyond direct @antv users — any project that pulled in echarts-for-react or size-sensor as a transitive dependency was also exposed. Socket.dev researchers measured a median detection-to-publication gap of just 6.7 minutes, which is fast by industry standards, but automated CI pipelines that run npm install on every commit or nightly build can execute a malicious preinstall script well within that window. GitHub's response was correspondingly large: the company removed 640 malicious package versions and revoked 61,274 npm granular access tokens that had write permissions and 2FA-bypass scope, cutting off reuse of any credentials the malware had already stolen.
How Did the Attacker Compromise the @antv Account?
The attacker took over the "atool" npm account rather than exploiting a vulnerability in AntV's code itself. Public writeups have not disclosed whether the takeover happened through a phishing email, a leaked npm token, or credential stuffing, and AntV/atool have not published a detailed post-mortem — this is consistent with most npm maintainer-account compromises, where the initial access vector is rarely confirmed publicly even after the incident is contained. What is confirmed is that once the attacker held publish rights, they used npm's own release tooling to push new versions of legitimate, long-trusted packages, which is why the compromise slipped past version-pinning and typical "does this package look suspicious" checks: the package names, maintainers of record, and download counts were all exactly what a dependency-scanning tool would expect to see. This is the same structural weakness behind the original Shai-Hulud worm and the earlier event-stream and ua-parser-js incidents — a single maintainer credential is often the only thing standing between an attacker and every downstream consumer of a package.
What Does the Malicious Payload Actually Do?
The payload is a 486-498 KB obfuscated JavaScript file that runs automatically during npm install via a "preinstall": "bun run index.js" script and immediately begins harvesting secrets from more than 130 file paths on the host. Once running, it targets AWS access keys and session tokens, GCP service account files, Azure service principal credentials, GitHub Personal Access Tokens and OIDC tokens, npm publish tokens, Kubernetes service account tokens, HashiCorp Vault credentials, SSH private keys, database connection strings, Docker auth files, and cryptocurrency wallet files. On GitHub Actions runners specifically, it goes further than reading environment variables like GITHUB_TOKEN and ACTIONS_ID_TOKEN_REQUEST_TOKEN — it reads the Runner.Worker process's memory directly through /proc/[pid]/mem to recover tokens that were never written to disk or environment at all. Researchers also observed the malware dropping persistence artifacts into .claude/ and .vscode/ directories and attempting privilege escalation through sudoers rule injection, which means a single infected build agent can remain compromised well after the malicious package version is removed from npm.
How Does the Malware Exfiltrate Stolen Credentials?
The malware uses a dual-channel exfiltration design so that losing one channel doesn't stop the theft. Stolen data is first encrypted with AES-256-GCM using RSA-OAEP-wrapped keys, then the primary channel commits the encrypted blob to branches or new repositories under the attacker's control — StepSecurity counted more than 2,200 public GitHub repositories created purely as data dead-drops, some using the legitimate, heavily trafficked antvis/G2 repository's commit history as cover. When the GitHub API path is blocked or rate-limited, the malware falls back to a direct HTTPS connection to t.m-kosche.com on port 443, sending stolen credentials to the path /api/public/otel/v1/traces — a URL structure deliberately chosen to look like routine OpenTelemetry trace export so it blends into normal outbound monitoring traffic. Network defenders looking for indicators should watch for a python-requests/2.31.0 user-agent on outbound connections and for repositories whose descriptions contain the reversed string "niagA oG eW ereH :duluH-iahS" or Dune-themed naming patterns such as "sayyadina-stillsuit-852," both of which researchers flagged as campaign markers left by the TeamPCP tooling.
Is Mini Shai-Hulud the Same as the Original Shai-Hulud Worm?
No — Mini Shai-Hulud is a related but distinct campaign that borrows the name, branding, and general credential-theft goal of the original Shai-Hulud worm from September 2025 without reproducing its self-replicating propagation mechanic. The original Shai-Hulud worm automatically republished itself into every package a compromised maintainer had access to, creating a cascading, self-spreading outbreak. Mini Shai-Hulud, observed across multiple waves including this AntV incident, instead relies on a single compromised account per target ecosystem and a faster, more surgical publish burst — in this case 639 versions in roughly ten minutes — aimed at maximizing CI/CD credential capture before defenders can react, rather than spreading indefinitely from package to package. Researchers tracking the campaign put its cumulative total at 1,055 malicious versions across 502 packages spanning npm, PyPI, and Composer registries as of this wave, indicating TeamPCP is running the same playbook across multiple language ecosystems rather than limiting it to JavaScript.
What Should Organizations Do Right Now?
Organizations that touch any of the affected packages should treat this as an active incident requiring credential rotation, not just a dependency bump. First, rotate every CI/CD secret that any build agent running the compromised versions could have accessed — GitHub tokens, AWS and GCP keys, npm publish tokens, and Vault credentials — since the payload was specifically built to harvest all of these. Second, search lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml) for any of the 323 affected package names at the compromised version ranges published between 01:56 and 02:06 UTC on May 19, 2026, and pin to versions published before that window. Third, delete node_modules entirely and reinstall from verified-clean versions rather than trusting an in-place update, since the payload drops persistence artifacts outside the package directory itself, in .claude/ and .vscode/. Finally, audit GitHub organizations for unauthorized repositories, branches, or workflow changes created since May 19 — the 2,200+ dead-drop repositories this campaign created are a useful hunting signal even for teams that don't believe they were directly affected.
How Safeguard Helps
Safeguard's reachability analysis would have flagged that @antv/g2 and echarts-for-react were not just present in a manifest but actually loaded at runtime in exposed build and deployment paths, cutting through the noise of hundreds of transitively-pulled packages to show which services were genuinely at risk from the compromised versions. Griffin AI, Safeguard's investigative agent, correlates a malicious-package alert like this one against your actual dependency graph, CI/CD configuration, and outbound network policy to tell you within minutes whether a preinstall script like bun run index.js had the opportunity to run and exfiltrate credentials in your environment — not just whether the package version appears somewhere in your repos. Safeguard continuously generates and ingests SBOMs across every repository and build pipeline, so when an incident like the AntV compromise breaks, you can query "where is this exact version running" across your entire fleet in seconds instead of grepping lockfiles by hand. And when a fix is available, Safeguard opens auto-fix pull requests that pin affected packages to clean, verified versions and strip malicious preinstall hooks, so remediation ships as fast as the attack did.