npm and PyPI Supply Chain Malware: How to Detect AI-Poisoned Packages in 2026
Supply chain attacks on npm and PyPI now account for the majority of software-delivered malware, and the packages targeting AI infrastructure are the most dangerous variant your team will face this year. Sonatype’s 2026 State of the Software Supply Chain report identified over 454,600 new malicious packages in 2025 alone, bringing the cumulative total of confirmed malware to 1.233 million packages, a 75% increase year over year. What those numbers obscure is the specific shift in targeting: attackers have moved from random spray-and-pray poisoning to precision strikes on the packages sitting at the center of your AI pipeline.
Two incidents from March 2026 illustrate exactly how far the methodology has evolved. On March 24, 2026, LiteLLM versions 1.82.7 and 1.82.8 were published to PyPI with a three-stage credential-stealing payload that swept AWS credentials, Kubernetes configs, SSH keys, and CI/CD secrets from every environment that ran pip install during a three-hour window before PyPI quarantined the packages. On March 30-31, 2026, attackers compromised the axios npm account and published versions 1.14.1 and 0.30.4 carrying a dependency on [email protected], a trojanized package that deployed a full remote access trojan within six minutes of publication. Axios has 100 million weekly downloads. The attack poisoned both the 1.x and 0.x branches within 39 minutes.
This guide gives you the detection methodology, tool chain, and workflow that existing content on this topic does not: specifically how to catch AI-targeted packages, how SBOM generation fits into an active response, and where the current tooling has genuine gaps.
Why AI-Targeted Supply Chain Attacks Are Different
The targeting logic behind the LiteLLM attack was not accidental. LiteLLM is a Python middleware library that routes calls to more than 100 LLM APIs, including OpenAI, Anthropic, AWS Bedrock, Google Vertex AI, and Azure OpenAI, through a single interface. A developer environment running LiteLLM holds credentials for every AI provider simultaneously. Where a typical web application might have a database connection string and a single API key, an AI application using LiteLLM accumulates credentials with a density an order of magnitude higher than conventional stacks.
That credential density is exactly why these packages get targeted. Attackers linked to the LAPSUS$ actor group have been running a coordinated campaign since at least December 2025, hitting developer tooling specifically: Trivy (the container security scanner), Checkmarx KICS (the infrastructure-as-code scanner), and LiteLLM in the same campaign. Each tool is trusted, runs with elevated permissions, and executes early in build pipelines. The attack surface is inseparable from how modern AI development works.
The September 2025 npm attack documented by Palo Alto Networks is the same pattern at JavaScript scale: 18 widely used packages poisoned in a coordinated operation that put billions of weekly downloads at risk. Sonatype’s data shows that 99% of all open source malware in 2025 appeared in npm. The registry is the primary battleground, and most teams are scanning it with tools built for a different era.
The Detection Gap: Where npm Audit and pip-audit Fall Short
The standard tooling, npm audit and pip-audit, operates against a known vulnerability database. Both tools are useful and should be running in your pipeline, but they have a structural blind spot that attackers exploit deliberately.
npm audit checks your dependency tree against the npm Advisory Database. It catches packages with disclosed CVEs and packages that have been formally reported as malicious after the fact. It does not catch a malicious package that was published 30 minutes ago. In the axios attack, Socket flagged the malicious plain-crypto-js dependency within six minutes of publication, at 00:05:41 UTC on March 31. npm audit would have returned clean results for hours, potentially days, depending on advisory lag.
pip-audit queries the Python Packaging Advisory Database and OSV. The same timing constraint applies. In the LiteLLM attack, PyPI quarantined the malicious versions within three hours of publication. For a package with 3.4 million daily downloads, that three-hour window exposed a significant number of environments before any advisory existed to catch it.
The deeper issue with both tools is that they check for known vulnerabilities, not behavioral signals. The LiteLLM 1.82.8 payload was embedded in a .pth file placed in site-packages/ with a correctly declared entry in the wheel’s RECORD file and a matching hash. Running pip install --require-hashes would have passed clean because the malicious package was published using legitimately stolen credentials. The attack bypassed hash verification not by breaking it, but by going through it.
The Tool Chain That Actually Catches This
A detection-capable supply chain security workflow requires layering four capabilities: real-time behavioral scanning, lockfile and manifest analysis, SBOM generation, and continuous monitoring. Here is how each tool fits.
Socket: Behavioral Analysis for npm and PyPI
Socket differs from audit-based tools by analyzing package behavior rather than cross-referencing a vulnerability database. It runs static analysis on packages at publish time and flags signals like new install scripts, obfuscated code, new network access, file system access, and package metadata anomalies. In the axios incident, Socket detected the malicious plain-crypto-js dependency within six minutes using automated behavioral analysis, not a human report.
Socket integrates as a GitHub App, replacing the default npm audit check on pull requests. When a PR introduces a dependency that triggers behavioral signals, Socket blocks the merge and provides a detailed breakdown. The plain-crypto-js dropper used a custom two-layer obfuscation scheme: reversed Base64 with underscore-to-padding substitution, followed by XOR cipher using the key OrDeR_7077. Socket’s scanner flagged the obfuscation pattern before any analyst decoded the payload manually.
For Python, Socket added PyPI support in 2024. The same behavioral analysis applies: install hooks, obfuscated imports, suspicious network calls at import time.
Snyk: Dependency Tree Scanning with License Visibility
Snyk Open Source scans your full dependency tree, including transitive dependencies, and surfaces known vulnerabilities with fix guidance. Where Socket focuses on behavioral signals, Snyk focuses on the vulnerability database and provides CVSS scores, fix versions, and reachability analysis, telling you whether a vulnerable code path is actually called by your application.
For npm, run: npx snyk test --all-projects
For Python: snyk test --file=requirements.txt
Snyk’s strength in the supply chain context is transitive dependency visibility. The @qqbrowser/openclaw-qbot package in the axios attack distributed a tampered copy of [email protected] inside its own node_modules/. Teams that only checked their direct dependencies missed it entirely. Snyk traverses the full tree.
pip-audit and npm audit: Your Baseline, Not Your Strategy
Both tools run fast, are free, and should be in every CI pipeline as a baseline check. They catch known CVEs and formally reported malicious packages. They are the floor, not the ceiling, of supply chain defense.
For npm: npm audit --audit-level=moderate
For Python: pip-audit --requirement requirements.txt --output=json
Pin your lock files. package-lock.json and poetry.lock are your strongest defense against version-range poisoning. The axios attack exploited caret ranges: any project using ^1.14.0 pulled the malicious 1.14.1 automatically on the next npm install. Lockfiles prevent this.
| Tool | Detection Method | Real-Time Alerts | Transitive Deps | AI Package Support | Cost |
|---|---|---|---|---|---|
| Socket | Behavioral / static analysis | Yes (minutes) | Yes | npm, PyPI | Free tier / paid |
| Snyk Open Source | CVE database + reachability | No (advisory lag) | Yes | All ecosystems | Free tier / paid |
| npm audit | npm Advisory Database | No | Yes | npm only | Free |
| pip-audit | PyPA Advisory DB / OSV | No | Partial | PyPI only | Free |
| cdxgen | SBOM generation | No | Yes | All ecosystems | Free (OWASP) |
| Syft | SBOM generation | No | Yes | All ecosystems | Free (Anchore) |
SBOM Generation: Your Incident Response Weapon
A Software Bill of Materials (SBOM) is a structured inventory of every package in your application and its dependency tree. During the LiteLLM incident, the three questions that immediately mattered were: which repositories run LiteLLM, are any running versions 1.82.7 or 1.82.8, and which environments had credentials in scope? Most teams answered those questions by asking engineers on Slack. Teams with current SBOMs answered them in minutes.
Two formats dominate: CycloneDX and SPDX. CycloneDX, maintained by OWASP, is purpose-built for security use cases and integrates directly with vulnerability scanning pipelines. SPDX, the Linux Foundation standard and ISO/IEC 5962:2021, is better established in compliance and licensing contexts. For security operations, CycloneDX is the more practical choice.
Generating SBOMs with cdxgen
cdxgen is the official SBOM generation tool of OWASP and supports npm, PyPI, Go, Maven, Cargo, and more than a dozen other ecosystems. Install it and run it against your project root:
For a Node.js project: npx @cyclonedx/cdxgen -o sbom.json --type nodejs .
For a Python project: pip install cdxgen && cdxgen -o sbom.json --type python .
The output is a JSON document listing every component, its version, its package URL (purl), and its hash. That purl is the query key you use to cross-reference against vulnerability feeds like OSV (Google’s Open Source Vulnerability database), which covers npm, PyPI, Go, Maven, and GitHub Advisory Database in a single API.
Generating SBOMs with Syft
Syft, from Anchore, generates SBOMs from directories, container images, and OCI artifacts. For teams running containerized AI workloads, Syft’s ability to scan a Docker image directly is particularly useful:
For a directory: syft dir:. -o cyclonedx-json > sbom.json
For a container image: syft my-ai-app:latest -o cyclonedx-json > sbom.json
Pair Syft with Grype (also from Anchore) to run vulnerability matching against the SBOM: grype sbom:sbom.json. This two-step pattern, generate then scan, gives you a documented artifact you can compare across deploys to identify what changed between a clean build and a potentially compromised one.
Automating SBOM in CI/CD
The SBOM is only useful if it is current. Generate it on every build, not on demand during an incident. A minimal GitHub Actions step:
- name: Generate SBOM
run: npx @cyclonedx/cdxgen -o sbom.json --type nodejs .
- name: Upload SBOM artifact
uses: actions/upload-artifact@v3
with:
name: sbom
path: sbom.json
Store SBOMs with the same retention policy as your build artifacts. During the LiteLLM incident, teams that could compare the SBOM from a clean March 23 build against a March 24 build immediately spotted the introduction of the malicious versions. Teams without stored SBOMs had no clean baseline to compare against.
Detecting AI-Specific Attack Patterns
The attacks targeting AI infrastructure share a set of behavioral signatures that general supply chain tooling does not explicitly prioritize. Understanding these patterns lets you tune your detection and set up targeted alerts.
The Postinstall Hook Pattern
The plain-crypto-js malware executed via the postinstall npm lifecycle hook, running node setup.js immediately after installation, before your application ever starts. This is one of the highest-signal indicators of malicious intent in a new or updated dependency. Legitimate packages use postinstall hooks for native module compilation (node-gyp), but a postinstall hook that makes outbound network calls, reads environment variables, or writes files outside the package directory is a red flag.
Socket flags postinstall hooks that include network access as a behavioral signal. You can audit your own lockfile for packages with install scripts using: cat package-lock.json | grep -A2 "hasInstallScript": true
Unicode and Homoglyph Obfuscation
One of the emerging techniques in AI-targeted package attacks uses Unicode lookalike characters in source code. A function named ехес using Cyrillic “е” and “с” is visually identical to the ASCII exec but will not match signature-based detection patterns. Malicious packages have used this technique to hide calls to eval, exec, and subprocess invocations from basic static analysis. Socket’s scanner detects Unicode-confusable identifiers as part of its behavioral analysis.
For Python specifically, pip-audit does not flag this. You can run a basic check on your installed packages using:
python3 -c "import ast, sys; ast.parse(open(sys.argv[1]).read())" suspicious_file.py
Malformed Unicode that passes visual inspection will often fail the AST parser, surfacing the obfuscation.
Dependency Confusion and Typosquatting
Dependency confusion attacks target the package resolution order in environments that have both internal and public registries configured. If your private registry serves my-internal-package at version 1.0.0 and an attacker publishes my-internal-package at version 9.0.0 on the public registry, npm’s default resolution will prefer the higher public version. The fix is explicit registry scoping in your .npmrc and a private registry that does not fall back to the public registry for scoped packages.
Typosquatting remains simpler and more common: reqests instead of requests, lodsh instead of lodash. The plain-crypto-js package was initially published as a clean typosquat of the legitimate crypto-js library 18 hours before the malicious version appeared. That staging period is itself a behavioral signal: a new package mimicking a legitimate one with no downstream dependents is worth scrutiny before you add it to your lockfile.
The .pth File Attack Vector
The LiteLLM 1.82.8 attack introduced a technique that most Python security tooling does not scan for. A .pth file placed in site-packages/ executes automatically on every Python interpreter startup, including when pip runs, when IDE language servers initialize, and during CI/CD build steps. This means the payload fires before your application code runs and persists even if you uninstall the package without checking for the .pth file explicitly.
Audit your Python environments with:
find $(python3 -c "import site; print(' '.join(site.getsitepackages()))") -name "*.pth" -newer /tmp/last_audit_marker
Any .pth file containing base64-encoded content, subprocess calls, or exec statements is an immediate incident indicator. Removing the compromised package without also removing the .pth file leaves the persistence mechanism intact.
Indicators of Compromise: The March 2026 Attacks
If your team runs Node.js or Python workloads, verify your environments against these specific indicators from the March 2026 campaign.
For the axios / plain-crypto-js attack, check for:
- axios versions 1.14.1 or 0.30.4 in your package-lock.json or node_modules
- plain-crypto-js versions 4.2.0 or 4.2.1 anywhere in your dependency tree
- Network traffic to
sfrclak[.]comor IP142.11.206.73 - File
/Library/Caches/com.apple.act.mondon macOS - File
%PROGRAMDATA%\wt.exeon Windows (renamed PowerShell) - File
/tmp/ld.pyon Linux - HTTP POST requests with body matching
packages[.]npm[.]org/product0,product1, orproduct2
For the LiteLLM PyPI attack (litellm 1.82.7, 1.82.8), check for:
- File
~/.config/sysmon/sysmon.py(backdoor persistence) - Systemd service “System Telemetry Service” (
~/.config/systemd/user/sysmon.service) - Files
/tmp/tpcp.tar.gz,/tmp/session.key,/tmp/payload.enc - Kubernetes pods named
node-setup-{node_name}in the kube-system namespace - Outbound HTTPS to
models.litellm.cloudor recurring GET requests tocheckmarx.zone/rawevery five minutes
Removing the compromised packages does not remove the Stage 3 persistence from the LiteLLM attack. If you ran the affected versions, treat it as an active incident: rotate all credentials the environment had access to, check for the sysmon backdoor, and audit your Kubernetes clusters for unauthorized pods.
Building a Detection Workflow Your CI/CD Can Enforce
Detection without enforcement is noise. The goal is to make it structurally impossible to merge a dependency that has not passed your defined checks, and to alert within minutes when a package in your production dependency tree gets flagged after release.
A practical three-layer workflow for DevSecOps teams:
Layer 1: Pre-merge gates. Install the Socket GitHub App to replace npm audit on pull requests. Configure Snyk to block merges that introduce high-severity vulnerabilities without a suppression comment from a security reviewer. Require lockfile commits: no package.json or requirements.txt change merges without the corresponding lockfile update.
Layer 2: Build-time SBOM generation. Generate a CycloneDX SBOM on every build using cdxgen or Syft. Upload it as a build artifact. Run it through OSV Scanner or Grype before the build passes. Any new vulnerability that was not present in the previous build’s SBOM creates a blocking alert.
Layer 3: Continuous post-publish monitoring. Socket and Snyk both offer monitoring that alerts when a package already in your dependency tree gets newly flagged. This is the layer that catches the axios scenario: your build passed clean on March 30, but on March 31 [email protected] is flagged, and you need to know within minutes, not hours. Set up these alerts and route them to your security Slack channel, not just email.
For teams running AI infrastructure specifically, add a fourth check: audit your Python site-packages for unexpected .pth files on every deployment using the find command above. This adds under two seconds to a build and catches the most dangerous persistence mechanism in the 2026 AI supply chain attack toolbox.
The AI security threat landscape in 2026 has moved well beyond perimeter defense, and your dependency pipeline is now a primary attack surface. Teams that have not treated their package registries as adversarial infrastructure are operating with a structural gap in their security posture. The incidents from this month are not anomalies; they are the template for what comes next. Getting your SBOM workflow current, installing behavioral scanning at the registry level, and setting up post-publish alerts gives you a defensible posture today rather than a retroactive audit after a breach.
Shield Operations offers incident response planning specifically for UK organisations facing supply chain compromise scenarios. If your team needs to build out or test your detection capabilities before the next axios-scale event, that is the starting point.
Frequently Asked Questions
What is an npm supply chain attack?
An npm supply chain attack occurs when an attacker introduces malicious code into a package published on the npm registry, either by compromising a maintainer’s account, publishing a typosquat of a legitimate package, or injecting a malicious transitive dependency. When developers run npm install, the malicious code executes on their machines or CI/CD infrastructure. The axios attack in March 2026 compromised a maintainer account to publish two versions containing a remote access trojan, affecting a package with 100 million weekly downloads.
Does npm audit detect newly published malicious packages?
No. npm audit checks your dependency tree against the npm Advisory Database, which is populated with known vulnerabilities after they have been disclosed and reported. A package published an hour ago will return a clean audit result even if it contains active malware. Behavioral analysis tools like Socket flag suspicious packages within minutes of publication by analyzing install hooks, obfuscation patterns, and network access in the package code itself, independent of any advisory database.
What is an SBOM and why does it matter for supply chain security?
A Software Bill of Materials (SBOM) is a structured inventory of every package component in your application, including transitive dependencies, versions, and cryptographic hashes. During a supply chain incident, an SBOM lets you answer immediately: which of our builds included the affected package version? Without a current SBOM, that question requires manually checking every repository. The LiteLLM PyPI attack in March 2026 hit packages with 3.4 million daily downloads; teams with automated SBOM generation identified their exposure in minutes rather than hours.
What makes AI pipeline packages a higher-value target than standard libraries?
AI pipeline packages like LiteLLM, LangChain, and LlamaIndex hold credentials for every cloud provider the application uses simultaneously: AWS Bedrock, Anthropic, OpenAI, GCP, Azure. A conventional web application might hold one database credential. An AI application running through a unified LLM proxy holds credentials with a density an order of magnitude higher. Attackers who compromise a single package in this stack harvest everything in one operation. The LiteLLM attack collected AWS credentials, Kubernetes configs, SSH keys, CI/CD secrets, and cloud service account files from every affected environment.
How do you detect a .pth file supply chain attack in Python?
Run: find $(python3 -c "import site; print(' '.join(site.getsitepackages()))") -name "*.pth" -exec grep -l "base64\|subprocess\|exec" {} \; Any .pth file containing base64-encoded content, subprocess calls, or exec statements is a compromise indicator. The LiteLLM 1.82.8 attack used this mechanism because .pth files execute automatically on every Python interpreter startup, including during pip install, and survive package removal unless explicitly deleted. Uninstalling the compromised package without checking for the .pth file leaves the persistence mechanism running.
Should I use Socket or Snyk for npm supply chain protection?
Use both, because they catch different things. Socket performs behavioral analysis at publish time and catches novel malware within minutes, before any advisory exists. Snyk provides CVE database coverage with reachability analysis, telling you whether a vulnerable function is actually called in your application. Socket is the detection layer for zero-day supply chain attacks. Snyk is the coverage layer for known vulnerabilities. Running npm audit alone covers neither: it is a baseline check, not a supply chain security strategy.