AntV ecosystem npm packages hit by TeamPCP
Part of the Shai-Hulud hits npm and PyPI campaign
On 2026-05-19, TeamPCP took the shared atool npm account and published 639 malicious versions across 323 packages — most of the @antv ecosystem and a long tail of standalone neighbors. The bun-based dropper harvested CI/CD secrets and self-propagated via npm.
Story
Hundreds of npm packages from Alibaba's @antv data-visualization stack — plus a long tail of widely used JavaScript utilities that happened to share the same maintainer account — were hijacked over a 90-minute stretch on the morning of May 19, 2026, and republished as a self-spreading credential stealer.
The packages were all owned by an npm account called atool, the shared publishing handle behind the @antv namespace, several smaller scopes, and a grab-bag of standalone libraries including echarts-for-react, timeago.js, and size-sensor. Researchers at Socket, who first reported the activity, said the attacker pushed 639 malicious versions across 323 packages in two automated waves between 01:39 and 02:56 UTC. SafeDep and StepSecurity confirmed roughly the same scope. Wiz, which named the attacker TeamPCP, said the broader "Mini Shai-Hulud" wave that day reached 1,055 versions across 502 packages spanning npm, PyPI, and Composer — most of it driven by this single compromised account.
According to Socket, the attacker used two delivery paths. Most packages had their package.json rewritten with a preinstall or postinstall of bun run index.js, with the script dropped at the package root. A second set instead pointed at a poisoned commit in the antvis/G2 GitHub repository through optionalDependencies, where a prepare hook ran the same code. The payload itself was a half-megabyte, heavily obfuscated Bun script that walked the disk for credentials covering every major cloud provider, Kubernetes, HashiCorp Vault, SSH, and database connection files, then read /proc/*/mem on GitHub Actions runners to pull masked CI/CD secrets out of the Runner.Worker process in plaintext.
The payload behaved like a worm. Given any usable npm token, it would validate the credential, enumerate every package the account could publish, fetch each package's latest tarball, inject the same dropper, and republish. Exfiltration ran to t.m-kosche.com over HTTPS disguised as OpenTelemetry trace traffic, with bodies wrapped in AES-256-GCM and RSA-OAEP. When the HTTPS channel failed, the malware fell back to GitHub itself, committing harvested data to public repositories on stolen developer accounts. The repositories were named under a Dune theme, with the campaign's banner reversed in the description. Socket counted between 2,200 and 2,500 such repositories by the end of the day. On infected hosts, the payload also rewrote editor and CI configuration files and, on macOS, registered a LaunchAgent for a backdoor named kitty.
Socket said it flagged most malicious versions within six to twelve minutes of publish, with a median of 6.7 minutes, and npm reclassified them as known malware. In its own writeup, Wiz attributed the operation to TeamPCP at moderate confidence based on shared infrastructure, the firedalazer dead-drop tag, payload kinship with other campaigns, and reuse of the kitty backdoor and Dune-themed repositories elsewhere in the same wave. The same backdoor surfaced a few hours later in the Nx Console VS Code extension compromise (see [[nx-console]]), and Wiz said credentials stolen in the @antv wave were later used to publish a malicious Microsoft Python SDK to PyPI (see [[durabletask-pypi]]). The cross-ecosystem aggregate lives on [[shai-hulud-here-we-go-again]]; this record holds the @antv-account evidence.
Affected Artifacts
- Observed
- 2026-05-19
- Compromised Versions
- Unknown
- Fixed
- Not listed
- Includes @antv/g2, @antv/g6, @antv/x6, @antv/l7, @antv/s2, @antv/f2, @antv/g, @antv/g2plot, @antv/graphin, @antv/data-set, and roughly 150 additional supporting libraries; per-version coverage is enumerated in the Socket and StepSecurity posts.
- Observed
- 2026-05-19
- Compromised Versions
- Unknown
- Fixed
- Not listed
- Reported at 1.1 to 1.5 million weekly downloads at time of compromise.
- Observed
- 2026-05-19
- Compromised Versions
- Unknown
- Fixed
- Not listed
- Reported at roughly 1.5 million weekly downloads at time of compromise.
- Observed
- 2026-05-19
- Compromised Versions
- Unknown
- Fixed
- Not listed
- Observed
- 2026-05-19
- Compromised Versions
- Unknown
- Fixed
- Not listed
- Observed
- 2026-05-19
- Compromised Versions
- Unknown
- Fixed
- Not listed
- Observed
- 2026-05-19
- Compromised Versions
- Unknown
- Fixed
- Not listed
Incident Context
- Motive
- Credential Theft Data Exfiltration
- Attribution
- Group
- Cause
- Compromised Account Credentials
- Transitive
- Yes
- Actor
- TeamPCP
Indicators
- Locationdistribution: npmjs.com/~atool
- Locationmirror: github.com/antvis
- fileindex.js
- commandbun run index.js
- file~/.local/share/kitty/cat.py
- file~/Library/LaunchAgents/com.user.kitty-monitor.plist
- file~/.config/systemd/user/kitty-monitor.service
- file.claude/settings.json
- file.claude/setup.mjs
- file.vscode/tasks.json
- file.vscode/setup.mjs
- file.github/workflows/codeql.yml
- domaint.m-kosche.com
- domainm-kosche.com
- ipv4185.95.159.32
- urlhttps://t.m-kosche.com:443/api/public/otel/v1/traces
- tagfiredalazer
- tagniagA oG eW ereH :duluH-iahS
- file_sha256cat.py: fb5c97557230a27460fdab01fafcfabeaa49590bafd5b6ef30501aa9e0a51142
- file_sha1cat.py: 783b4019fc5b942a29846132d28441c8fc31bed8
- file_md5cat.py: b06b126b9e26af03a7ef2f8b8e90d446
- accountatool (npm)
Notes
- Compromised maintainer was the shared npm account atool per Socket. Wiz tracked the same account's GitHub credentials being reused to enter the microsoft/durabletask-python repository later the same day.
- Socket's count of 639 weaponized versions across 323 unique packages is the most inclusive published number. Lower counts elsewhere (SafeDep 637/314, StepSecurity 500+, Wiz 400+ @antv) reflect earlier or scope-limited tallies. The atool account maintained 547 packages total. The broader same-day Mini Shai-Hulud total per Socket was 1,055 versions across 502 unique packages spanning npm, PyPI, and Composer.
- Publishing windows reported differ slightly: SafeDep places the two automated waves at 01:39 to 02:06 UTC; Socket places overall publish activity at 01:56 to 02:56 UTC. Both agree on the May 19 date and the two-wave structure.
- Compromised maintainer was the shared atool npm account, email i@hust.cc, associated with @antv, @lint-md, @openclaw-cn, @starmind scopes plus a long tail of standalone JavaScript and tooling packages.
- SafeDep notes the payload is identical to the Mini Shai-Hulud toolkit used in the earlier SAP compromise the same week.
- Wiz also reported same-day compromises of the GitHub Actions actions-cool/issues-helper and actions-cool/maintain-one-comment using shared infrastructure, plus the nrwl.angular-console VS Code extension v18.95.0 (tracked separately as nx-console).
External References
Source record: oss/attacks/antv-npm/meta.yaml