Back to Feed
Supply ChainApr 24, 2026

The npm Threat Landscape: Attack Surface and Mitigations

Unit 42 reports npm supply chain attacks evolved post-Shai-Hulud with wormable malware and CI/CD persistence.

Summary

Unit 42 analyzes the evolution of npm ecosystem threats following the September 2025 Shai-Hulud worm, which automated malware distribution across packages. The report documents a coordinated TeamPCP campaign compromising Checkmarx distribution channels (Docker Hub, GitHub Actions, VS Code extensions, npm) via credential theft and multi-stage payloads designed to evade detection. Modern npm attacks now prioritize token theft, CI/CD pipeline persistence, and self-propagation across developer toolchains.

Full text

Threat Research CenterHigh Profile ThreatsMalware Malware The npm Threat Landscape: Attack Surface and Mitigations 12 min read Related ProductsAdvanced DNS SecurityAdvanced URL FilteringCloud-Delivered Security ServicesCortexCortex CloudUnit 42 Incident Response By:Unit 42 Published:April 24, 2026 Categories:High Profile ThreatsMalware Tags:Credential HarvestingGitHubNpm packagesObfuscationPayloadSupply chainWorm propagation Share Executive Summary The security of the npm ecosystem reached a critical inflection point in September 2025. The Shai-Hulud worm, a self-replicating malware that automated the compromise and redistribution of malicious packages, marked the end of the “nuisance” era of npm attacks and the beginning of a high-consequence threat landscape. Since that watershed moment, Unit 42 has tracked an aggressive acceleration in the frequency and technical depth of supply chain compromises. Attacks have evolved from a series of isolated typosquatting incidents into systematic campaigns by various threat actors to weaponize the trust that powers modern software development. The New Baseline for npm Threats The Shai-Hulud incident proved that the npm registry could be used as a force multiplier for malware distribution. In the months following, we have observed three core shifts in adversary TTPs: Wormable propagation: Malicious payloads now prioritize the theft of npm tokens and GitHub Personal Access Tokens (PATs) to automatically infect and republish legitimate packages, as seen in the March 2026 Axios compromise. Infrastructure-level persistence: Attackers are no longer just stealing data; they are embedding themselves into continuous integration/continuous delivery (CI/CD) pipelines to attain long-term, undetectable access to enterprise environments. Multi-stage payloads: Following the September 2025 template, current attacks often deploy dormant “sleeper” dependencies that only activate under specific environmental conditions to evade automated scanners. npm Attacks Seen As a Whole npm compromises have common themes. In the post-Shai-Hulud era, we believe it is helpful to consider the attack surface as a whole. This article will combine: Details of major incidents: Real-time analysis of significant package compromises (e.g., Shai-Hulud 2.0, Axios, Chalk/Debug) Cross-campaign correlation: Identifying common infrastructure or code snippets that link disparate attacks to the same threat actors Remediation playbooks: Actionable guidance for rotating credentials and purging malicious dependencies from local and cloud-based caches Shai-Hulud: A New Wave A malicious npm package published as @bitwarden/cli version 2026.4.0 was identified as part of a broader supply-chain campaign attributed to TeamPCP. The package impersonates the legitimate Bitwarden CLI password manager. Upon installation, it executes a multi-stage payload that steals credentials from cloud providers, CI/CD systems and developer workstations. It then self-propagates by backdooring every npm package the victim can publish. It has been noted that inside public GitHub repositories that were published contained the string “Shai-Hulud: The Third Coming.” Attackers deployed the same payload across multiple Checkmarx distribution channels, indicating a coordinated campaign to weaponize compromised developer tooling credentials to maximize the area of impact: Docker Hub images GitHub Actions VS Code extensions Palo Alto Networks customers are better protected from the threats described in this article through the following products and services: Advanced WildFire Advanced URL Filtering and Advanced DNS Security Cortex Cloud The Unit 42 Incident Response team can also be engaged to help with a compromise or to provide a proactive assessment to lower your risk. Related Unit 42 Topics Supply Chain, Credential Harvesting, Obfuscation, Backdoor April 2026 - Shai Hulud: A New Wave Broader Campaign Context According to Checkmarx's official security update, this npm package is one component of a broader supply-chain campaign that simultaneously compromised multiple Checkmarx distribution channels: Docker Hub: Poisoned checkmarx/kics images (v2.1.20, v2.1.21, latest, alpine, debian) GitHub Actions: Malicious checkmarx/ast-github-action v2.3.35 VS Code extensions: Backdoored checkmarx/ast-results (v2.63, v2.66) and checkmarx/cx-dev-assist (v1.17, v1.19) npm: The @bitwarden/cli package analyzed in this report Per Checkmarx's disclosure, all artifacts share the same C2 infrastructure (audit.checkmarx[.]cx), the same obfuscation techniques and the same credential harvesting and propagation logic. The VS Code extension variant delivered its payload (mcpAddon.js) from a backdated orphan commit in Checkmarx's own GitHub repository, making the download URL appear trustworthy. TeamPCP (@pcpcats) publicly took credit for the compromise. Per Socket's analysis, the group had previously targeted Checkmarx infrastructure in March 2026, along with Trivy and LiteLLM, suggesting an ongoing campaign against security tooling vendors. Attack Overview Table 1 shows the attributes of the attack. Attribute Detail Package @bitwarden/cli@2026.4.0 Trigger preinstall lifecycle script Runtime Bun v1.3.13 (downloaded during install) C2 server audit.checkmarx[.]cx:443 (94.154.172[.]43) C2 path /v1/telemetry Fallback C2 Dynamic, fetched via GitHub Search API dead drop Exfiltration HTTPS POST (encrypted) + GitHub public repos Attribution TeamPCP (@pcpcats) Table 1. Attributes of the attack. Stage 1: Bootstrap - bw_setup.js The package.json provides two execution paths for the malicious script, as shown in Figure 1. Figure 1. Execution paths for the malicious script in the package.json file. The preinstall hook runs automatically during npm install. The bin field registers bw_setup.js as the bw command, symlinking it into the user's PATH. Since the legitimate Bitwarden CLI also uses bw as its binary name, this serves as a secondary trigger. Even if preinstall is blocked (e.g., via --ignore-scripts), the malware executes the next time the user or any script invokes bw. The shebang line #!/usr/bin/env node at the top of bw_setup.js ensures it runs as a Node.js script when called directly. The bootstrap script performs three actions: Platform detection: Identifies the OS and architecture (Linux, macOS, Windows; x64 or arm64), including musl versus glibc detection on Linux. Bun runtime download: Downloads the Bun JavaScript runtime (v1.3.13) from the official github[.]com/oven-sh/bun releases. This is needed because the main payload uses Bun-specific APIs (shell execution, file I/O, gzip) not available in Node.js. Payload execution: Runs bw1.js using the freshly downloaded Bun binary. A custom ZIP extraction implementation is included to avoid any dependencies, making the bootstrap entirely self-contained. Stage 2: The Payload - bw1.js The payload is an approximately 10 MB single-line JavaScript file containing approximately 285,000 lines when formatted. It bundles legitimate software developer kits (SDKs) (e.g., AWS SDK, Google Cloud client libraries, Azure Identity, Octokit, jsonwebtoken, tar) alongside the malicious orchestration code. Obfuscation Techniques The code employs multiple layers of obfuscation: String table rotation: A function _0x214e resolves hex indices to strings from a large rotated array (_0x1ee1), breaking simple static string analysis. Seeded ASCII shuffle cipher: Sensitive strings (domains, file paths, shell commands) are encoded as arrays of numeric indices into a Fisher-Yates-shuffled ASCII table. The shuffle uses a linear congruential PRNG seeded with 0x3039 (12345), as shown below in Figure 2. Figure 2. Seeded ASCII shuffle cipher. The 128-character ASCII set is shuffled deterministically, producing a substitution table where an index with the hex value 0x42 maps to the ASCII character a, 0x6e to u. For example, the C2 domain is stored as [0x42, 0x6e, 0x36, 0x4b, 0x2b, 0x5c, 0xd, 0x57, 0x0, 0xd, 0x7

Indicators of Compromise

  • domain — audit.checkmarx.cx
  • ip — 94.154.172.43
  • malware — Shai-Hulud
  • malware — Shai-Hulud 2.0

Entities

TeamPCP (threat_actor)Bitwarden CLI (product)Checkmarx KICS (product)Axios (product)Palo Alto Networks (vendor)npm (technology)