@antv maintainer takeover (atool) — Mini Shai-Hulud burst across ~300 packages
On 2026-05-19 the compromised npm publisher atool (Alibaba / AntV co-maintainer) pushed an automated burst of 639 malicious versions across 323 unique packages — the entire @antv visualization suite plus widely-used unscoped libraries including echarts-for-react, size-sensor, and timeago.js (>15M combined monthly downloads). Each release adds a preinstall: bun run index.js hook running the Mini Shai-Hulud credential-stealer. Attributed to TeamPCP.
- Threat actor
- TeamPCP
- Detected by
- Socket · JFrog · Microsoft · Aikido · OX Security · Snyk · SafeDep
- Also known as
- Mini Shai-Hulud · AntV burst
- Ecosystems
- npm
- Packages tracked
- 298
What happened
On 2026-05-19 between 01:39 and 02:06 UTC, the npm publisher account atool (an Alibaba / AntV co-maintainer) was compromised and used as the launch point for an automated burst of malicious releases. Socket telemetry continued seeing publishes through ~02:56 UTC; detections fired until ~03:09 UTC. After reconciliation across Socket, JFrog Security Research, Aikido, OX Security, Snyk, GBHackers, The Hacker News, BleepingComputer, and Microsoft Threat Intelligence, the final tally is 639 malicious versions across 323 unique packages — up from the initial 598+/297+ estimate.
Affected scope spans the entire @antv visualization suite (g-*, g2-*, g6-*, x6-*, l7-*, s2-*, f2-*/f-*, dipper-*, gi-assets-*, li-*, and ~120 other @antv/* packages), @lint-md/*, smaller scopes (@starmind/*, @openclaw-cn/*), plus unscoped high-traffic packages including echarts-for-react (3.0.7 / 3.1.7 / 3.2.7 — 1.1M weekly downloads), size-sensor (1.0.4 / 1.1.4 / 1.2.4 — 4.2M monthly), timeago.js (4.1.2 / 4.2.2 — 1.15M monthly), jest-canvas-mock, jest-date-mock, canvas-nest.js, mcp-echarts, and mcp-mermaid. Combined estimated exposure on the unscoped packages alone exceeds 15M monthly downloads.
Each compromised release adds a preinstall: bun run index.js hook; 597 of 598 versions also inject an optionalDependencies entry pointing at imposter commits in antvis/G2 that deliver a second copy of the payload — a novel persistence vector that survives npm rebuild and resists lockfile-only audits. The payload is a 498KB obfuscated Bun script matching the Mini Shai-Hulud toolkit used in the SAP / @cap-js (April 2026), TanStack (May 11), and same-day durabletask PyPI compromises — same scanner architecture, same credential regex set, same obfuscation pattern. Attribution to TeamPCP is consistent across Socket, The Hacker News, SafeDep, and JFrog.
A novel capability in this wave: the payload can generate valid Sigstore provenance attestations by abusing OIDC tokens harvested from compromised CI runners, allowing the malicious packages to pass standard provenance verification despite carrying credential-stealing malware.
- Payload SHA-256 (Microsoft):
a68dd1e6a6e35ec3771e1f94fe796f55dfe65a2b94560516ff4ac189390dfa1c - Backdoor Python script SHA-256 (Microsoft):
fb5c97557230a27460fdab01fafcfabeaa49590bafd5b6ef30501aa9e0a51142 - GitHub force-removed all 640 malicious package versions and invalidated 61,274 npm granular access tokens that carried write permission with 2FA bypass.
- Stealer scope: AWS / GCP / Azure (metadata + env), GitHub PATs + npm publish tokens, Kubernetes service-account tokens and kubeconfig, HashiCorp Vault tokens, Stripe keys, database connection strings, SSH keys,
.envand.env.*secrets, plus a Docker host-socket container-escape attempt.
The cleanest known version per package is always the one immediately preceding the malicious pair (e.g. @antv/g2@5.4.8, @antv/g6@5.1.1, echarts-for-react@3.0.6, size-sensor@1.0.3, timeago.js@4.0.2).
Affected packages (298)
- npm
@antv/a80.1.10.2.1 - npm
@antv/adjust0.3.50.4.5 - npm
@antv/algorithm0.2.260.3.26 - npm
@antv/async-hook2.3.92.4.9 - npm
@antv/attr0.4.50.5.5 - npm
@antv/ava3.5.13.6.1 - npm
@antv/ava-react3.4.23.5.2 - npm
@antv/awards0.1.90.2.9 - npm
@antv/calendar-heatmap1.2.21.3.2 - npm
@antv/chart-linter1.2.61.3.6 - npm
@antv/chart-node-g60.1.40.2.4 - npm
@antv/chart-visualization-skills0.2.30.3.3 - npm
@antv/ckb2.1.42.2.4 - npm
@antv/color-schema0.3.30.4.3 - npm
@antv/color-util2.1.62.2.6 - npm
@antv/component2.2.112.3.11 - npm
@antv/coord0.5.70.6.7 - npm
@antv/d3-color1.1.01.2.0 - npm
@antv/d3-interpolate1.1.31.2.3 - npm
@antv/data-samples1.1.11.2.1 - npm
@antv/data-set0.12.80.13.8 - npm
@antv/data-wizard2.1.42.2.4 - npm
@antv/dipper-component0.1.40.2.4 - npm
@antv/dipper-hooks0.3.10.4.1 - npm
@antv/dipper-map1.1.101.2.10 - npm
@antv/dom-util2.1.42.2.4 - npm
@antv/dumi-theme-antv0.9.40.10.4 - npm
@antv/dw-analyzer1.2.51.3.5 - npm
@antv/dw-random1.2.71.3.7 - npm
@antv/dw-transform1.2.71.3.7 - npm
@antv/dw-util1.2.41.3.4 - npm
@antv/event-emitter0.2.30.3.3 - npm
@antv/expr1.1.21.2.2 - npm
@antv/f-charts0.1.00.2.0 - npm
@antv/f-engine1.11.01.12.0 - npm
@antv/f-lottie1.11.01.12.0 - npm
@antv/f-my1.11.01.12.0 - npm
@antv/f-react1.11.01.12.0 - npm
@antv/f-test-utils1.1.91.2.9 - npm
@antv/f-vue1.11.01.12.0 - npm
@antv/f-wx1.11.01.12.0 - npm
@antv/f25.15.05.16.0 - npm
@antv/f2-algorithm5.8.05.9.0 - npm
@antv/f2-canvas1.1.51.2.5 - npm
@antv/f2-context0.1.10.2.1 - npm
@antv/f2-graphic0.1.160.2.16 - npm
@antv/f2-my4.1.524.2.52 - npm
@antv/f2-react5.15.05.16.0 - npm
@antv/f2-site4.1.424.2.42 - npm
@antv/f2-vue4.1.334.2.33 - npm
@antv/f2-wordcloud5.15.05.16.0 - npm
@antv/f2-wx4.1.514.2.51 - npm
@antv/f60.1.190.2.19 - npm
@antv/f6-alipay0.1.70.2.7 - npm
@antv/f6-core0.1.20.2.2 - npm
@antv/f6-element0.1.10.2.1 - npm
@antv/f6-hammerjs0.1.20.2.2 - npm
@antv/f6-plugin1.1.61.2.6 - npm
@antv/f6-ui1.1.31.2.3 - npm
@antv/f6-wx0.1.70.2.7 - npm
@antv/g6.4.16.5.1 - npm
@antv/g-base0.6.160.7.16 - npm
@antv/g-camera-api2.1.452.2.45 - npm
@antv/g-canvas2.3.02.4.0 - npm
@antv/g-canvaskit1.2.11.3.1 - npm
@antv/g-compat1.1.111.2.11 - npm
@antv/g-components2.1.422.2.42 - npm
@antv/g-css-layout-api1.1.381.2.38 - npm
@antv/g-css-typed-om-api1.1.381.2.38 - npm
@antv/g-device-api1.7.131.8.13 - npm
@antv/g-dom-mutation-observer-api2.1.422.2.42 - npm
@antv/g-gesture3.1.423.2.42 - npm
@antv/g-image-exporter1.1.421.2.42 - npm
@antv/g-layout-blocklike1.8.491.9.49 - npm
@antv/g-lite2.8.02.9.0 - npm
@antv/g-lottie-player1.2.11.3.1 - npm
@antv/g-math3.2.03.3.0 - npm
@antv/g-mobile1.2.51.3.5 - npm
@antv/g-mobile-canvas1.2.11.3.1 - npm
@antv/g-mobile-canvas-element1.1.421.2.42 - npm
@antv/g-mobile-svg1.2.11.3.1 - npm
@antv/g-mobile-webgl1.2.11.3.1 - npm
@antv/g-pattern2.1.422.2.42 - npm
@antv/g-perf1.1.01.2.0 - npm
@antv/g-plugin-3d2.2.12.3.1 - npm
@antv/g-plugin-a11y1.5.11.6.1 - npm
@antv/g-plugin-annotation1.3.01.4.0 - npm
@antv/g-plugin-box2d2.2.12.3.1 - npm
@antv/g-plugin-canvas-path-generator2.2.262.3.26 - npm
@antv/g-plugin-canvas-picker2.4.12.5.1 - npm
@antv/g-plugin-canvas-renderer2.6.12.7.1 - npm
@antv/g-plugin-canvaskit-renderer2.4.12.5.1 - npm
@antv/g-plugin-control2.2.12.3.1 - npm
@antv/g-plugin-css-select2.2.12.3.1 - npm
@antv/g-plugin-device-renderer2.7.12.8.1 - npm
@antv/g-plugin-dom-interaction2.2.312.3.31 - npm
@antv/g-plugin-dragndrop2.2.12.3.1 - npm
@antv/g-plugin-gesture2.2.12.3.1 - npm
@antv/g-plugin-gpgpu1.10.201.11.20 - npm
@antv/g-plugin-html-renderer2.4.12.5.1 - npm
@antv/g-plugin-image-loader2.4.12.5.1 - npm
@antv/g-plugin-matterjs2.2.12.3.1 - npm
@antv/g-plugin-mobile-interaction1.1.421.2.42 - npm
@antv/g-plugin-physx2.2.12.3.1 - npm
@antv/g-plugin-rough-canvas-renderer2.2.12.3.1 - npm
@antv/g-plugin-rough-svg-renderer2.2.12.3.1 - npm
@antv/g-plugin-svg-picker2.1.462.2.46 - npm
@antv/g-plugin-svg-renderer2.5.12.6.1 - npm
@antv/g-plugin-webgl-device1.10.171.11.17 - npm
@antv/g-plugin-webgl-renderer1.1.261.2.26 - npm
@antv/g-plugin-webgpu-device1.10.171.11.17 - npm
@antv/g-plugin-yoga2.4.12.5.1 - npm
@antv/g-plugin-zdog-canvas-renderer2.2.12.3.1 - npm
@antv/g-plugin-zdog-svg-renderer2.2.12.3.1 - npm
@antv/g-shader-components2.1.02.2.0 - npm
@antv/g-svg2.2.12.3.1 - npm
@antv/g-web-animations-api2.2.322.3.32 - npm
@antv/g-web-components2.2.12.3.1 - npm
@antv/g-webgl2.2.12.3.1 - npm
@antv/g-webgl-compute0.1.10.2.1 - npm
@antv/g-webgpu2.2.12.3.1 - npm
@antv/g-webgpu-compiler0.8.20.9.2 - npm
@antv/g-webgpu-core0.8.20.9.2 - npm
@antv/g-webgpu-engine0.8.20.9.2 - npm
@antv/g-webgpu-raytracer0.6.10.7.1 - npm
@antv/g-webgpu-unitchart0.6.10.7.1 - npm
@antv/g25.5.85.6.8 - npm
@antv/g2-brush0.1.20.2.2 - npm
@antv/g2-extension-3d0.3.00.4.0 - npm
@antv/g2-extension-ava0.3.00.4.0 - npm
@antv/g2-extension-plot0.3.20.4.2 - npm
@antv/g2-plugin-slider2.2.12.3.1 - npm
@antv/g2-ssr0.3.00.4.0 - npm
@antv/g2plot2.5.352.6.35 - npm
@antv/g2plot-schemas1.3.21.4.2 - npm
@antv/g65.2.15.3.1 - npm
@antv/g6-alipay0.1.10.2.1 - npm
@antv/g6-cli0.1.40.2.4 - npm
@antv/g6-core0.9.240.10.24 - npm
@antv/g6-editor1.3.01.4.0 - npm
@antv/g6-element0.9.250.10.25 - npm
@antv/g6-extension-3d0.2.230.3.23 - npm
@antv/g6-extension-react0.3.70.4.7 - npm
@antv/g6-mobile0.2.20.3.2 - npm
@antv/g6-pc0.9.250.10.25 - npm
@antv/g6-plugin0.9.250.10.25 - npm
@antv/g6-plugin-map-view0.1.40.2.4 - npm
@antv/g6-plugins1.1.91.2.9 - npm
@antv/g6-react-node1.5.81.6.8 - npm
@antv/g6-ssr0.2.10.3.1 - npm
@antv/g6-wx0.1.10.2.1 - npm
@antv/gatsby-theme0.2.00.3.0 - npm
@antv/geo-coord1.1.81.2.8 - npm
@antv/gi-assets-advance2.6.222.7.22 - npm
@antv/gi-assets-algorithm2.4.192.5.19 - npm
@antv/gi-assets-basic2.5.402.6.40 - npm
@antv/gi-assets-galaxybase1.3.151.4.15 - npm
@antv/gi-assets-graphscope2.2.152.3.15 - npm
@antv/gi-assets-hugegraph1.2.151.3.15 - npm
@antv/gi-assets-janusgraph1.2.151.3.15 - npm
@antv/gi-assets-neo4j2.2.152.3.15 - npm
@antv/gi-assets-scene2.3.212.4.21 - npm
@antv/gi-assets-tugraph2.2.152.3.15 - npm
@antv/gi-assets-tugraph-analytics0.3.150.4.15 - npm
@antv/gi-assets-xlab0.2.300.3.30 - npm
@antv/gi-cli1.3.111.4.11 - npm
@antv/gi-common-components1.4.161.5.16 - npm
@antv/gi-mock-data1.1.51.2.5 - npm
@antv/gi-public-data1.1.11.2.1 - npm
@antv/gi-sdk3.1.03.2.0 - npm
@antv/gi-sdk-app1.3.101.4.10 - npm
@antv/gi-theme-antd0.7.110.8.11 - npm
@antv/github-config-cli0.2.00.3.0 - npm
@antv/gl-matrix2.8.12.9.1 - npm
@antv/gpt-vis1.1.01.2.0 - npm
@antv/gpt-vis-ssr0.4.70.5.7 - npm
@antv/graphin3.1.53.2.5 - npm
@antv/graphin-components2.5.12.6.1 - npm
@antv/graphin-graphscope1.1.51.2.5 - npm
@antv/graphin-icons1.1.01.2.0 - npm
@antv/graphlib2.1.42.2.4 - npm
@antv/hierarchy0.8.10.9.1 - npm
@antv/infographic0.3.190.4.19 - npm
@antv/interaction0.2.50.3.5 - npm
@antv/istanbul0.1.00.2.0 - npm
@antv/knowledge1.2.41.3.4 - npm
@antv/l72.26.102.27.10 - npm
@antv/l7-component2.26.102.27.10 - npm
@antv/l7-composite-layers0.18.10.19.1 - npm
@antv/l7-core2.26.102.27.10 - npm
@antv/l7-district2.4.122.5.12 - npm
@antv/l7-draw3.2.53.3.5 - npm
@antv/l7-editor1.2.131.3.13 - npm
@antv/l7-extension-g-layer1.1.01.2.0 - npm
@antv/l7-layers2.26.102.27.10 - npm
@antv/l7-leaflet1.1.21.2.2 - npm
@antv/l7-map2.26.102.27.10 - npm
@antv/l7-mapkit0.6.00.7.0 - npm
@antv/l7-maps2.26.102.27.10 - npm
@antv/l7-mini2.21.82.22.8 - npm
@antv/l7-pass1.1.01.2.0 - npm
@antv/l7-react2.5.32.6.3 - npm
@antv/l7-renderer2.26.102.27.10 - npm
@antv/l7-scene2.26.102.27.10 - npm
@antv/l7-source2.26.102.27.10 - npm
@antv/l7-three2.26.102.27.10 - npm
@antv/l7-utils2.26.102.27.10 - npm
@antv/l7plot0.6.110.7.11 - npm
@antv/l7plot-component0.1.110.2.11 - npm
@antv/larkmap1.6.11.7.1 - npm
@antv/layout-gpu1.2.71.3.7 - npm
@antv/layout-wasm1.5.21.6.2 - npm
@antv/li-aiearth-assets0.5.70.6.7 - npm
@antv/li-analysis-assets1.10.11.11.1 - npm
@antv/li-core-assets1.4.71.5.7 - npm
@antv/li-editor1.7.11.8.1 - npm
@antv/li-p21.9.21.10.2 - npm
@antv/li-sam-assets0.2.40.3.4 - npm
@antv/li-sdk1.6.11.7.1 - npm
@antv/lite-insight2.2.12.3.1 - npm
@antv/matrix-util3.1.43.2.4 - npm
@antv/mcp-server-antv0.2.80.3.8 - npm
@antv/mcp-server-chart0.10.100.11.10 - npm
@antv/my-f22.2.72.3.7 - npm
@antv/my-f2-pc0.2.10.3.1 - npm
@antv/narrative-text-editor0.3.200.4.20 - npm
@antv/narrative-text-schema0.4.70.5.7 - npm
@antv/narrative-text-vis0.4.160.5.16 - npm
@antv/path-util3.1.13.2.1 - npm
@antv/react-g2.2.12.3.1 - npm
@antv/s22.8.12.9.1 - npm
@antv/s2-react2.4.12.5.1 - npm
@antv/s2-react-components2.2.22.3.2 - npm
@antv/s2-ssr0.2.10.3.1 - npm
@antv/s2-vue2.3.02.4.0 - npm
@antv/sam0.3.00.4.0 - npm
@antv/scale0.6.20.7.2 - npm
@antv/semantic-release-pnpm1.1.41.2.4 - npm
@antv/smart-color0.3.10.4.1 - npm
@antv/stat0.1.20.2.2 - npm
@antv/t80.4.00.5.0 - npm
@antv/thumbnails2.1.02.2.0 - npm
@antv/thumbnails-component2.1.02.2.0 - npm
@antv/torch1.1.61.2.6 - npm
@antv/translator1.1.11.2.1 - npm
@antv/util3.4.113.5.11 - npm
@antv/vendor1.1.111.2.11 - npm
@antv/vis-predict-engine0.2.10.3.1 - npm
@antv/webgpu-graph1.1.01.2.0 - npm
@antv/word-scale-chart0.4.40.5.4 - npm
@antv/wx-f22.2.12.3.1 - npm
@antv/x63.2.73.3.7 - npm
@antv/x6-angular-shape3.1.13.2.1 - npm
@antv/x6-components0.11.70.12.7 - npm
@antv/x6-react0.2.260.3.26 - npm
@antv/x6-react-shape3.1.13.2.1 - npm
@antv/x6-vector1.5.21.6.2 - npm
@antv/x6-vue-shape3.1.23.2.2 - npm
@antv/x6-vue3-shape1.1.01.2.0 - npm
@antv/xflow2.2.132.3.13 - npm
@antv/xflow-diff1.1.01.2.0 - npm
@lint-md/cli2.1.02.2.0 - npm
@lint-md/core2.1.02.2.0 - npm
@lint-md/parser0.1.140.2.14 - npm
ai-figure0.5.00.6.0 - npm
amapcn0.2.20.3.2 - npm
ast-plugin0.1.70.2.7 - npm
babel-plugin-version0.3.30.4.3 - npm
boring-avatars-vanilla1.1.21.2.2 - npm
byte-parser1.1.01.2.0 - npm
canvas-nest.js2.1.42.2.4 - npm
echarts-for-react3.0.73.1.73.2.7 - npm
filesize.js2.1.02.2.0 - npm
fixed-round1.1.21.2.2 - npm
gantt-for-react0.3.00.4.0 - npm
jest-canvas-mock2.5.32.6.32.7.3 - npm
jest-date-mock1.0.111.1.111.2.11 - npm
jest-electron0.2.120.3.12 - npm
jest-expect0.1.10.2.1 - npm
jest-less-loader0.3.00.4.0 - npm
jest-random-mock1.1.01.2.0 - npm
jest-url-loader0.2.00.3.0 - npm
limit-size0.2.40.3.4 - npm
lint-md0.3.00.4.0 - npm
lint-md-cli0.2.20.3.2 - npm
mcp-echarts0.8.10.9.1 - npm
mcp-mermaid0.5.10.6.1 - npm
miz1.1.11.2.1 - npm
onfire.js2.1.12.2.1 - npm
react-adsense0.2.00.3.0 - npm
relationship.js1.3.91.4.9 - npm
ribbon.js1.1.2 - npm
size-sensor1.0.41.1.41.2.4 - npm
slice.js1.2.11.3.1 - npm
timeago-react3.1.73.2.7 - npm
timeago.js4.1.24.2.2 - npm
word-width1.1.11.2.1 - npm
xmorse1.1.01.2.0
Impact
- AWS, GCP, Azure credentials (instance metadata + env)
- GitHub Personal Access Tokens and npm publish tokens — enables further worm propagation
- Kubernetes service account tokens and kubeconfig files
- HashiCorp Vault tokens, Stripe keys, database connection strings
- SSH private keys and .env / .env.* secrets
- Docker container escape attempt via the host socket
- preinstall hook runs even with
npm ci --ignore-scriptsonly if Bun is present — butbun runis invoked directly, bypassing standard npm script gating
What to do
- 1Block / pin away from every (name, version) pair in the packages map below. For top-impact packages: pin
@antv/g2to<= 5.4.8,@antv/g6to<= 5.1.1,@antv/x6to<= 3.1.7,echarts-for-reactto<= 3.0.6,size-sensorto<= 1.0.3,timeago.jsto<= 4.0.2,jest-canvas-mockto<= 2.5.2,jest-date-mockto<= 1.0.10 - 2Purge node_modules and any cached tarballs published between 2026-05-19T01:39Z and 2026-05-19T02:10Z
- 3Assume credential compromise on any CI runner or developer machine that ran
npm install/pnpm install/yarn installagainst any of these packages during the exposure window. Rotate npm/GitHub/GitLab/CircleCI tokens, AWS/GCP/Azure keys, K8s tokens, Vault tokens, Stripe keys, DB passwords - 4Audit
optionalDependenciesin every lockfile for entries pointing to antvis/G2 commit hashes — these are the secondary payload bootstrap - 5Audit your own npm publish history (under every maintainer account on the affected machines) for unexpected releases after 2026-05-19T01:30Z — the worm targets maintainer publish rights for propagation
- 6Block egress to known Mini Shai-Hulud C2 infrastructure shared with the SAP/TanStack waves; cross-reference IOCs from the Wiz and Socket reports on those campaigns
References
- SocketAntV packages compromised: Mini Shai-Hulud hits ~300 npm packagessocket.dev
- JFrogShai-Hulud, here we go again — May 19 burstresearch.jfrog.com
- MicrosoftMini Shai-Hulud compromised AntV npm packages enable CI/CD credential theftmicrosoft.com
- The Hacker NewsMini Shai-Hulud pushes malicious AntV npm packages via compromised maintainer accountthehackernews.com