What's new in v2 (July 2026): Coverage of the Shai-Hulud worm family — the first self-replicating npm supply chain attack, now in its third generation and the first campaign to span npm and PyPI simultaneously; the EU Cyber Resilience Act's September 11, 2026 vulnerability-reporting deadline; npm Trusted Publishing (OIDC) going GA as the successor to long-lived publish tokens; a new Agentic AI & MCP Supply Chain Risk section covering tool poisoning, MCP server SSRF exposure, and non-human identity governance; and updated 2025–2026 malicious-package statistics from Sonatype and Socket.
🗺
Threat Landscape
// Why supply chain security is the defining challenge of this decade
Software supply chain attacks target the trusted dependencies, tools, and build processes used to create software — not the software itself. Attackers compromise one package or build system to reach thousands of downstream consumers. The 2020 SolarWinds breach, the 2021 Log4Shell vulnerability, the 2022 node-ipc protestware incident, and the 2025–2026 Shai-Hulud worm campaigns all share the same root: implicit trust in code we didn't write.
🚨
Scale of impact, 2026 data: Sonatype identified over 454,600 new malicious packages in 2025 alone — nearly all concentrated in npm — pushing the cumulative known-malware total past 1.23 million packages. The average enterprise application still depends on hundreds of direct packages and thousands of transitive ones. Worm-style campaigns like Shai-Hulud now propagate automatically across maintainer accounts without further attacker involvement, and large language models continue to invent plausible package names that attackers race to register.
The Three Layers of Supply Chain Risk
Source Code
Malicious contributions to open-source repos, compromised maintainer accounts, insider threats, and typosquatted package names that closely mimic trusted libraries.
Build & Packaging
Tampered build pipelines, unsigned release artifacts, compromised registries (npm, PyPI, Maven Central), and CI/CD system compromises that inject malicious code at packaging time.
Distribution & Runtime
Mirror poisoning, CDN tampering, dependency confusion attacks exploiting internal vs. public registry resolution, and protestware that activates based on runtime conditions.
Notable Incidents
Incident
Year
Vector
Scope
SolarWinds Orion
2020
Compromised build server; backdoor injected into signed release
18,000+ organizations
Log4Shell (Log4j)
2021
RCE via JNDI injection in ubiquitous logging library
Maintainer intentionally added file-wiping payload for RU/BY IPs
1M+ weekly downloads
PyTorch compromise
2022
Dependency confusion — torchtriton published to PyPI before official
Nightly build users
XZ Utils backdoor
2024
Long-term social engineering of maintainer; backdoor in liblzma
Linux distros globally
AI package hallucination
2023–
LLMs invent nonexistent package names; attackers publish them
All AI-assisted devs
Shai-Hulud worm
Sep 2025–
Self-replicating npm worm; steals credentials via phishing, then auto-publishes trojanized versions of every other package the compromised maintainer owns
796+ packages, 20M+ weekly downloads
Mini Shai-Hulud (cross-registry)
May 2026
Resurgence spanning npm and PyPI simultaneously in one coordinated campaign for the first time
170+ npm, 2 PyPI packages
AsyncAPI generator compromise
Jul 2026
Attacker gained push access to a branch and let the project's own legitimate GitHub Actions workflow publish the malicious release — carrying valid OIDC provenance
3 packages, monorepo-wide
⚠️
Legitimate provenance is not a guarantee of legitimate intent. The July 2026 AsyncAPI compromise is a landmark case: the malicious packages carried valid npm OIDC provenance attestations because they were published through the project's real, unmodified CI/CD pipeline — the attacker never touched a token or credential, only the source branch that pipeline built from. Signing and provenance prove what built the artifact, not that the inputs to the build were trustworthy. Source-integrity controls (branch protection, required reviews, commit signing) remain necessary even after SLSA and Sigstore are in place.
⚔️
Attack Vectors
// The techniques attackers use to compromise your dependencies
Critical
Dependency Confusion
Attacker publishes a public package with the same name as your private internal package. Package managers resolve public registries first, installing the malicious version.
Victim uses @mycompany/auth internally. Attacker publishes mycompany-auth to npm with higher version.
Critical
Typosquatting
Publishing packages with names nearly identical to popular libraries — one character off, swapped letters, or plausible misspellings that developers mistype.
Compromising a maintainer's registry credentials via phishing, credential stuffing, or leaked tokens — then publishing a malicious version of a trusted package.
ua-parser-js, event-stream, coa, rc npm packages were all hijacked this way.
High
Protestware / Sabotage
A legitimate maintainer intentionally inserts malicious code — often politically motivated, triggered conditionally by locale, IP range, or other runtime factors.
node-ipc (2022): file wiper activated for Russian IP addresses.
High
Build Pipeline Compromise
Injecting malicious code into the CI/CD pipeline after source code review — in build scripts, post-install hooks, or through compromised build tooling.
SolarWinds: malicious code injected during the build process, not present in source repo.
Medium
Malicious Install Scripts
Packages using postinstall, preinstall hooks to execute arbitrary shell commands the moment the package is installed — before any code review.
npm postinstall scripts execute automatically unless --ignore-scripts is used.
Critical
Self-Replicating Worms
Malware that harvests a compromised maintainer's credentials, then automatically discovers and trojanizes every other package that maintainer owns — spreading exponentially across the registry with no further attacker involvement.
Shai-Hulud (Sep 2025–): 3 campaign waves, 796+ npm packages, credentials exfiltrated to public GitHub repos.
High
Legitimate CI/CD Pipeline Abuse
Rather than stealing a publish token, the attacker gains push access to a source branch and lets the project's own, unmodified CI/CD workflow build and publish the malicious release — producing valid signatures and provenance.
AsyncAPI generator (Jul 2026): malicious release published via the project's real GitHub Actions workflow, OIDC provenance intact.
⚠️
The long-game attack: The XZ Utils backdoor (2024) involved a fake persona spending two years building trust with the maintainer, then slowly introducing the backdoor across multiple commits. Automated scanning cannot reliably catch this. Provenance verification, reproducible builds, and SLSA frameworks reduce (but cannot eliminate) this risk — and, as the 2026 AsyncAPI case shows, they cannot catch a compromise that happens entirely upstream of a legitimate, correctly-configured pipeline.
📋
What Is an SBOM?
// Software Bill of Materials — the ingredient list for your software
A Software Bill of Materials (SBOM) is a formal, machine-readable inventory of every component in a software artifact — direct dependencies, transitive dependencies, their versions, licenses, known vulnerabilities, and their relationships. Think of it as the nutrition label for software.
Vulnerability response — instantly identify if Log4j-equivalent is in any product
License compliance — catch GPL in a proprietary product before shipping
Procurement security — require SBOMs from vendors before purchase
Incident triage — know in minutes, not days, what's affected
Regulatory compliance — US EO 14028, EU Cyber Resilience Act mandate SBOMs
Software composition visibility — end "I didn't know we used that"
ℹ️
Executive Order 14028 (US, 2021) mandated that any software sold to the US federal government must be accompanied by an SBOM. The EU Cyber Resilience Act (CRA, 2024) extends similar requirements to products sold in the EU. SBOMs are rapidly becoming a contractual and legal requirement, not just a best practice.
📄
SPDX vs CycloneDX
// The two dominant SBOM formats — choose based on use case
SPDXISO/IEC 5962:2021
The Linux Foundation standard, ISO-ratified. Originally designed for license compliance, expanded to full SBOM. Widely accepted for regulatory compliance.
Formats: SPDX-TV (tag-value), JSON, RDF, YAML, XML
Strengths: License expression accuracy, ISO standard status, mature tooling, NTIA minimum element coverage, legal defensibility.
Best for: Legal/compliance teams, government procurement, license auditing, cross-industry interoperability.
Version: SPDX 2.3 / 3.0 · spdx.dev
CycloneDXOWASP Standard
The OWASP standard, security-first design. Purpose-built for vulnerability management, VEX, and DevSecOps integration. Rich security metadata.
SBOM generation in CI: Generate SBOMs at build time — not retroactively — so they accurately reflect the exact artifact produced. Attach the SBOM to the release artifact and sign it. Syft's OCI attestation support makes this straightforward for containerized workloads: the SBOM is stored alongside the image digest in the registry, not as a separate file to manage.
🔍
Consuming & Auditing SBOMs
// Grype, OSV-Scanner, and VEX-driven vulnerability triage
Vulnerability Scanning Against SBOMs
bashGrype — Anchore vulnerability scanner
# Install Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# Scan a container image directly
grype nginx:1.25
# Scan an existing SBOM
grype sbom:./sbom.spdx.json
grype sbom:./sbom.cdx.json
# Fail CI on Critical/High vulnerabilities only
grype sbom:./sbom.cdx.json --fail-on high
# Output structured JSON for pipeline consumption
grype sbom:./sbom.cdx.json -o json > vuln-report.json
# Use a VEX document to suppress known non-exploitable CVEs
grype sbom:./sbom.cdx.json --vex ./vex.json
# OSV-Scanner (Google) — cross-ecosystem, fast
osv-scanner --sbom=sbom.cdx.json
osv-scanner --lockfile=package-lock.json # also works on lockfiles
osv-scanner -r ./my-project # recursive directory scan
VEX — Vulnerability Exploitability eXchange
VEX documents let producers communicate whether a known CVE is actually exploitable in their product. This eliminates alert fatigue from CVEs that exist in a dependency but aren't reachable in your specific build or configuration.
// Regulatory requirements and vendor expectations
MUST — US Federal
US Executive Order 14028
Any software sold to US federal agencies must include an SBOM. CISA has published minimum element guidance aligned to NTIA standards. Required for FedRAMP authorization.
MUST — EU Market
EU Cyber Resilience Act (CRA)
Products sold in the EU with digital elements must maintain SBOMs, report actively exploited vulnerabilities within 24 hours, and support secure updates. Staged deadlines: conformity-assessment bodies live June 11, 2026; mandatory vulnerability & incident reporting via ENISA's Single Reporting Platform starts September 11, 2026; full enforcement December 11, 2027. Component-level SBOM visibility is a practical prerequisite for meeting the 24-hour reporting window, so treat it as a September 2026 requirement even though the formal SBOM mandate lands with full enforcement.
SHOULD — Healthcare
FDA Medical Device SBOMs
US FDA requires SBOMs for premarket submissions of medical devices with software. Must include all commercial, open-source, and off-the-shelf software components.
SHOULD — Enterprise Procurement
Vendor SBOM Requirements
Require SBOMs from all software vendors as a procurement condition. Specify CycloneDX 1.5+ or SPDX 2.3+ in contracts. Automate ingestion into your VDR (Vulnerability Disclosure Report) workflow.
⚠️
SBOM freshness: An SBOM is only useful if it reflects the current state of the artifact. Implement automated SBOM generation on every build, version it alongside release artifacts, and republish updated SBOMs when dependency updates occur — even if the application code hasn't changed.
🔑
Sigstore
// Keyless signing for the open-source era
Sigstore is an open standard and toolchain for signing, verifying, and protecting software artifacts without requiring teams to manage private key infrastructure. It uses ephemeral OIDC-based signing certificates and a transparency log (Rekor) to create a tamper-evident, publicly auditable record of all signing events.
Sigstore Components
Cosign
Signs and verifies container images, blobs, and OCI artifacts. Stores signatures in OCI registries alongside the artifact. The primary user-facing CLI tool.
Rekor
The immutable, append-only transparency log. Every signature event is recorded. Anyone can query Rekor to verify when and by whom an artifact was signed.
Fulcio
The OIDC-based certificate authority. Issues short-lived signing certificates (10-minute TTL) bound to an identity (GitHub Actions workflow, Google account, etc.) — no long-lived private keys.
Cosign — Signing & Verification
bashCosign — keyless signing via OIDC
# Install cosign
brew install cosign
# or: go install github.com/sigstore/cosign/v2/cmd/cosign@latest─── SIGNING ───────────────────────────────────────────────────────────────# Keyless sign a container image (OIDC identity — GitHub Actions, GCP, etc.)
cosign sign \
--yes \
ghcr.io/myorg/my-image@sha256:abc123...
# Sign with a key file (for air-gapped / non-OIDC environments)
cosign generate-key-pair # produces cosign.key + cosign.pub
cosign sign --key cosign.key ghcr.io/myorg/my-image@sha256:abc123
# Sign and attach an SBOM as an attestation
cosign attest \
--predicate sbom.cdx.json \
--type cyclonedx \
--yes \
ghcr.io/myorg/my-image@sha256:abc123
# Sign a blob / binary (e.g. a release tarball)
cosign sign-blob --yes ./my-app-linux-amd64.tar.gz \
--bundle bundle.json # saves sig + cert + rekor entry─── VERIFICATION ──────────────────────────────────────────────────────────# Verify keyless — enforce identity must be a GitHub Actions workflow
cosign verify \
--certificate-identity-regexp=https://github.com/myorg/my-repo/.* \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/myorg/my-image@sha256:abc123
# Verify with a public key
cosign verify --key cosign.pub ghcr.io/myorg/my-image@sha256:abc123
# Verify an SBOM attestation
cosign verify-attestation \
--type cyclonedx \
--certificate-identity-regexp=https://github.com/myorg/.* \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/myorg/my-image@sha256:abc123 \
| jq '.payload | @base64d | fromjson'
# Verify a blob
cosign verify-blob ./my-app-linux-amd64.tar.gz --bundle bundle.json \
--certificate-identity-regexp=https://github.com/myorg/.* \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
Always sign the digest, never the tag. Tags are mutable — latest can point to a different image tomorrow. Signatures attach to the immutable SHA-256 digest. If you sign myimage:latest, cosign resolves the digest at signing time, but consumers must verify against the digest to get the guarantee.
PyPI introduced OIDC-based Trusted Publishing in 2023; npm's version went generally available in July 2025 and became the default recommendation industry-wide after the 2025–2026 Shai-Hulud campaigns showed exactly what a stolen long-lived NPM_TOKEN makes possible. The mechanism is the same Sigstore-style keyless pattern applied to package publishing: your CI job exchanges a short-lived OIDC identity token (scoped to one repo, one workflow, one run) for a publish credential that expires in minutes and cannot be reused. Every trusted-publishing release automatically carries a signed provenance attestation — no separate --provenance flag required.
yamlPublishing to npm without a stored token
# .github/workflows/publish.yml — configure the matching# trusted publisher first at npmjs.com → package → Settings → Publishing accesspermissions:
id-token: write# npm exchanges this OIDC token for a short-lived publish credentialcontents: readjobs:
publish:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4with: { node-version: '22', registry-url: 'https://registry.npmjs.org' }
- run: npm ci
- run: npm publish# no NPM_TOKEN secret anywhere — OIDC handles auth
⚠️
Trusted publishing is not automatically safe — it moves the trust boundary, not away. The canonical PyPI publishing action had a disclosed flaw where a workflow triggered on pull_request could let a fork PR obtain a publish token via the OIDC exchange. Restrict trusted-publisher workflows to push / tag events, never pull_request, and enable "disallow tokens" in npm's publishing-access settings so classic token-based publishing is impossible even as a fallback.
🏛
SLSA Framework
// Supply chain Levels for Software Artifacts — tamper-evident provenance
SLSA (pronounced "salsa") is a security framework — now governed by a vendor-neutral OpenSSF steering committee — that defines build integrity guarantees to prevent tampering and improve artifact provenance. SLSA v1.0 renamed the old numeric levels to a "Build track" (Build L1–L3) and split source-integrity requirements into a separate, still-evolving Source track; v1.1 is the current stable release, with v1.2 in active development. The table below shows the current Build-track levels alongside the legacy numeric names practitioners still use informally.
Level (v1.0 / legacy)
Requirements
Guarantee
Typical Environment
Build L1(SLSA 1)
Build process is scripted/automated; provenance generated (may be unverified)
Basic documentation; not tamper-resistant
CI with any provenance generation
Build L2(SLSA 2)
Hosted build service; provenance is authenticated and signed
Builds from a specific hosted service; prevents some tampering
GitHub Actions, GitLab CI with provenance action
Build L3(SLSA 3)
Hardened build platform; builds from specific source repo; provenance non-forgeable by build service — required for federal procurement
Build source auditable; cannot be tampered by the build service itself
Hermetically sealed CI, provenance from trusted builder
Source track(spec evolving)
Two-party review of all source changes; verified history; hermetic, reproducible builds
Full auditability; addresses the "trusted-branch, malicious-commit" gap that Build-track levels alone don't cover
Build L3 provenance is now the baseline for U.S. federal procurement and is what the 2026 AsyncAPI-style attacks expose the limits of: Build-track provenance proves the build platform wasn't tampered with, but says nothing about whether the source commit it built from was legitimate. That gap is exactly what the still-maturing SLSA Source track is meant to close — pair Build L3 with branch protection, required reviews, and commit signing in the meantime.
// Structured claims about software supply chain steps
In-Toto is the attestation framework underlying SLSA provenance, SBOM attestations, and other supply chain claims. An attestation is a cryptographically signed statement: "this software was built from this source, using this tool, at this time, producing this output."
The real scale: An average Node.js application installs hundreds of packages including transitive deps. A typical node_modules folder contains code from thousands of unique contributors worldwide. You haven't reviewed 99%+ of it. The question isn't whether you trust it — it's whether you've made an informed decision.
Risk Dimensions for Every Dependency
Dimension
Low Risk
High Risk
Maintainer count
Multiple active maintainers, org-owned
Single maintainer, inactive for years
Dependency depth
Direct dep with few transitive deps
Deep transitive dep, many sub-dependencies
Install scripts
No postinstall/preinstall hooks
Executes shell commands on install
Network access in tests
All tests run offline
Tests or build scripts reach external URLs
Published vs. source diff
Reproducible build; source matches artifact
Can't reproduce the published artifact from source
License
MIT, Apache-2, BSD — permissive
GPL/AGPL — copyleft; Unknown — high risk
🛡
Hardening Dependencies
// Locking, pinning, private proxies, and allowlisting
Pin Exact Versions — Use Lockfiles
✓ Pinned — reproducible
# requirements.txt — exact version
requests==2.31.0
numpy==1.26.4
# package.json — no range prefixes
{
"dependencies": {
"express": "4.18.2"← exact
}
}
# Always commit lockfiles
package-lock.json ← commit this
poetry.lock ← commit this
Cargo.lock ← commit this
✕ Unpinned — supply chain risk
# requests>=2.0 — any future version
requests>=2.0.0
# ^ and ~ allow updates
{
"dependencies": {
"express": "^4.0.0"← allows 4.x
}
}
# .gitignore-ing lockfiles# means every install could differ
*.lock ← do NOT ignore
Private Package Proxies & Allowlisting
bashPrivate proxy configuration
# npm — route all installs through Artifactory / Nexus / Verdaccio
npm config set registry https://artifactory.mycompany.com/artifactory/api/npm/npm/
# pip — private PyPI proxy
pip install --index-url https://nexus.mycompany.com/repository/pypi/simple/ requests
# pip.conf (system-wide)
[global]
index-url = https://nexus.mycompany.com/repository/pypi-proxy/simple/
trusted-host = nexus.mycompany.com
# Maven — settings.xml with mirror
<mirror>
<id>central-proxy</id>
<mirrorOf>*</mirrorOf>
<url>https://nexus.mycompany.com/repository/maven-public/</url>
</mirror>
# Docker — always pull from internal mirror, never Docker Hub directly
DOCKER_MIRROR=registry.mycompany.com/dockerhub-proxy
# Prevent dependency confusion: namespace all internal packages# npm: use scoped packages @myorg/package-name# pip: register internal package names on PyPI as dummies# Or: configure Artifactory to only resolve @myorg scope from internal
Dependency Confusion — Specific Mitigations
MUST — npm
Use scoped packages + overrides
All internal packages must use a scoped name like @myorg/package. Configure npm to resolve @myorg/* exclusively from your private registry, never from the public npm registry.
MUST — pip
Claim internal names on PyPI
Publish placeholder/dummy packages on PyPI for every internal package name you use. An attacker can't publish a malicious version of a name that's already claimed. Use --no-index in air-gapped builds.
MUST — All
Block public registry in prod build
Production builds should only resolve from your internal proxy. Network-level egress rules or firewall policies should prevent build agents from reaching public registries directly.
Npm Audit & Lockfile Integrity
bashIntegrity verification
# npm — install with integrity check, no allow-downgrade
npm ci # respects lockfile exactly; fails if lockfile inconsistent
npm audit --audit-level=high # fail on high+ severity
npm audit fix # auto-remediate# pip — verify checksums
pip install --require-hashes -r requirements.txt
# requirements.txt with hashes:# requests==2.31.0 \# --hash=sha256:58cd2187423839... \# --hash=sha256:942c5a758f98d7...# pip-audit — dedicated audit tool
pip install pip-audit
pip-audit --requirement requirements.txt
pip-audit --output-format cyclonedx-json > vuln.cdx.json
# cargo — audit for Rust
cargo install cargo-audit
cargo audit
# Go — vulnerability check
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
🐛
Install-time execution is the primary Shai-Hulud lesson. Later worm variants execute during the preinstall phase — before tests, before code review, before you've even finished the install command — dramatically widening the blast radius across developer machines and CI runners. Default to npm install --ignore-scripts (or the equivalent for your package manager) in CI, allowlist the specific packages that legitimately need install scripts, enforce mandatory 2FA and "disallow tokens" for anyone with publish rights on packages you maintain, and add a short dependency cooldown window (don't auto-upgrade to a release less than a few days old) so the community has time to catch a freshly-published malicious version before it reaches you.
🤖
AI-Era & Agentic Threats
// Package hallucination, agentic AI / MCP supply chain risk, and LLM-assisted attacks
🚨
AI package hallucination is a live, weaponized threat. Large language models — including coding assistants — frequently invent plausible-sounding but nonexistent package names. Attackers monitor for these hallucinated names and publish malicious packages under those names. Any developer who follows an LLM's pip install or npm install suggestion without verification may install attacker-controlled code. The Shai-Hulud worm campaigns went further, specifically targeting AI developer toolchains — compromised packages included the Bitwarden CLI (secrets access) and tooling embedded across AI coding-agent workflows.
How the Attack Works
textAI hallucination → supply chain attack flow
Developer asks LLM: "How do I parse YAML in Python?"
LLM responds:
"You can use the `yaml-python-advanced` library:
pip install yaml-python-advanced
import yaml_python_advanced as ypa
data = ypa.parse(my_string)"
❌ PROBLEM: `yaml-python-advanced` doesn't exist.
The correct package is `pyyaml` (pip install pyyaml).
Attacker flow:
1. Collect hallucinated package names from LLM outputs
(research papers show 100s of unique invented names per session)
2. Register the name on PyPI / npm before any legitimate package exists
3. Include credential harvester, crypto miner, or backdoor in the package
4. Wait for developers to blindly run the install command an LLM suggested
5. Achieve code execution on developer machines and CI/CD pipelines
Always look up every package an LLM suggests on the official registry (pypi.org, npmjs.com) before running install. Verify: does this package exist? Is it what the LLM described? Check download counts, age, and maintainer history.
MUST
Use a package allowlist
Maintain an approved package list. Any package not on the list requires a security review and explicit approval before adding to the project — regardless of source (LLM, StackOverflow, colleague recommendation).
MUST
Block unknown packages in CI
CI pipelines should only install packages that are in the lockfile and verified against your internal proxy. Any new package must go through a review gate — not added directly in a PR.
SHOULD
Monitor LLM suggestions in PRs
Review PRs for AI-suggested package additions with the same scrutiny as code changes. Treat any requirements.txt or package.json diff as a security-relevant change requiring explicit review.
AI Coding Assistant Risks Beyond Package Hallucination
Outdated Dependency Advice
LLMs have training cutoffs and may recommend specific versions that are outdated or have known CVEs. The model cannot know about vulnerabilities disclosed after its training data cutoff.
Mitigation: Always run npm audit, pip-audit, or Grype after adding any LLM-suggested dependency.
Poisoned Training Data
Research demonstrates that code completion models can be trained or fine-tuned to suggest insecure coding patterns — SQL injection, hardcoded credentials, unsafe deserialization — with high confidence.
Mitigation: Treat all AI-generated code as untrusted user input. SAST scan everything. Code review is not optional.
Agentic AI & MCP Supply Chain Risk
By 2026, AI coding agents and the Model Context Protocol (MCP) — the open standard connecting LLMs to internal tools, repos, and data — had become a new and largely ungoverned supply chain layer. Gartner projects 40% of enterprise applications will embed task-specific AI agents by end of 2026, up from under 5% a year earlier. OWASP's Top 10 for Agentic Applications now tracks this formally as ASI04 — Agentic Supply Chain Risk: the exposure created when an agent depends on third-party tools, plugins, MCP servers, prompt templates, or retrieval sources that can alter its behavior, data access, or execution path at runtime.
🚨
The numbers are not reassuring. An analysis of 7,000+ public MCP servers found 36.7% potentially vulnerable to SSRF — in one proof of concept, researchers retrieved live AWS credentials from a misconfigured MCP server's cloud metadata endpoint. Separately, only 8.5% of MCP implementations use OAuth, and 88% of organizations reported a confirmed or suspected AI-agent security incident in the past year. A single skill-registry compromise (tracked as CVE-2026-25253) enabled one-click remote code execution across 42,900+ exposed instances in 82 countries.
Risk
What It Looks Like
Primary Control
MCP tool / server poisoning
A malicious or compromised MCP server returns tool definitions or results crafted to manipulate the agent's next action — the agentic analogue of a trojanized dependency
Allowlist known-good MCP servers; treat tool descriptions and outputs as untrusted input
Skill / plugin registry compromise
Agent "skills" published to public registries carry the same typosquatting, account-takeover, and unvetted-install risk as npm/PyPI packages — with no equivalent of a decade of registry hardening behind them yet
Vet skill sources before install; sandbox skill execution; never grant a skill more privilege than the task requires
Confused deputy / goal hijack
An agent with broad standing credentials is manipulated (via poisoned context or a malicious tool result) into taking actions outside its intended scope, using its own legitimate permissions
Scope agent credentials narrowly per task; require human-in-the-loop for high-impact actions
Non-human identity sprawl
Agents spawn sub-agents and hold standing credentials across systems that were never designed to govern a non-human principal — only 23% of organizations have a formal agent-identity strategy
Issue short-lived, per-task credentials (the OIDC pattern already used by Sigstore and trusted publishing); audit-log every agent action
MUST
Treat MCP servers as dependencies
Every MCP server an agent can call is a supply chain component. Inventory them, pin versions, review changes, and apply the same allowlist discipline used for npm/PyPI packages — including scanning MCP servers published as npm packages for the ecosystem vulnerabilities they inherit.
MUST
Scope, don't trust, agent credentials
Never give an agent standing credentials broader than a junior engineer would have. Prefer short-lived, task-scoped tokens over long-lived API keys, and log every tool call with the agent's session ID for auditability.
SHOULD
Discover and inventory agent endpoints
Scan your environment for MCP endpoints (/mcp, /sse) and flag any bound to 0.0.0.0. You cannot secure agent infrastructure you don't know exists — shadow AI deployments were flagged by 76% of organizations in 2026, up from 61% the year prior.
SHOULD
Map to OWASP and NIST guidance
Use the OWASP Top 10 for Agentic Applications and OWASP Non-Human Identity Top 10 to classify agent-specific risks, and the NIST AI Risk Management Framework for governance requirements — both are the emerging baseline auditors will ask about.
🔭
Scanning & Detection
// OSV, Grype, Trivy, Dependabot, and behavioral detection
Vulnerability Databases
Database
Coverage
Format
URL
OSV
All ecosystems (PyPI, npm, Go, Maven, crates.io, GitHub)
JSON / API
osv.dev
NVD
CVEs across all software; authoritative CVSS scores
// The supply chain security checks every pipeline should enforce
Every stage of the CI/CD pipeline is an opportunity to detect and block supply chain compromise. Security gates should fail the build — not just warn — on violations.
Pin GitHub Actions by SHA, not tag.uses: actions/checkout@v4 is a mutable tag — it could point to different code tomorrow if the action repo is compromised. Use the full SHA: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683. Tools like Renovate and Dependabot can keep SHA pins up to date automatically.
🚨
Incident Response
// When a dependency is compromised — the first 60 minutes
textSupply chain incident runbook
T+0 min — DETECTION
□ Source of intelligence: CVE feed / security advisory / internal scan
□ Identify the affected package: name, version range, registry
□ Query your SBOM inventory: which products and versions use this package?
→ grype sbom:*.cdx.json | grep package-name
→ osv-scanner --sbom=*.json
□ Open incident bridge; notify security team lead
T+5 min — SCOPING
□ Are affected versions deployed in production? Which environments?
□ Is the vulnerability exploitable in your usage context? (VEX analysis)
□ What is the CVSS score? Is there a public PoC exploit?
□ Are customers / external services exposed?
T+15 min — CONTAINMENT (if actively exploitable)
□ Isolate affected services from external network if RCE/critical
□ Block malicious outbound connections if package exfiltrates data
□ Rotate any credentials that may have been exposed
□ Enable enhanced logging on affected systems
T+20 min — REMEDIATION
□ Pin to patched version in all affected repos
□ Open emergency PRs; fast-track review + merge
□ Trigger emergency CI/CD pipeline run
□ Deploy patched artifacts to all affected environments
□ Rebuild and re-sign container images; push new SBOMs
T+45 min — VERIFICATION
□ Re-run vulnerability scan against patched SBOM — confirm CVE resolved
□ Verify patched images are deployed across all environments
□ Confirm no indicators of compromise in logs (data exfil, reverse shell, etc.)
T+60 min — COMMUNICATION
□ Customer notification (if applicable, per SLA/regulatory requirements)
□ Internal post-incident summary to stakeholders
□ Update VEX documents for any CVEs deemed not_affected in other products
POST-INCIDENT
□ Blameless post-mortem within 5 business days
□ Update SBOM freshness SLA if gap discovered
□ Add new detection rule for class of vulnerability
□ Review dependency update frequency policy
⚖️
Compliance & Policy
// License compliance, allowlists, and policy-as-code
License Compliance
License Type
Examples
Commercial Use
Copyleft Risk
Permissive
MIT, Apache-2.0, BSD-2-Clause, ISC
✓ Free to use
None
Weak Copyleft
LGPL-2.1, MPL-2.0, EUPL
Conditional — if modified, share changes
Library modifications must be open
Strong Copyleft
GPL-2.0, GPL-3.0
⚠ Derivative works must be GPL
May require open-sourcing your product
Network Copyleft
AGPL-3.0
⚠ Even SaaS use triggers copyleft
Most restrictive for SaaS businesses
Commercial Restriction
BUSL-1.1, SSPL, CC-NC
✗ Commercial use prohibited or restricted
Legal review required
Policy-as-Code with OPA and Syft
bashLicense and vulnerability policy enforcement
# license_finder — Ruby gem, works across ecosystems
gem install license_finder
license_finder # scan current project
license_finder approve --name lodash # approve specific package
license_finder permitted_licenses add MIT Apache-2.0 BSD-2-Clause ISC
license_finder restricted_licenses add AGPL-3.0 GPL-3.0
# In CI — fail if any restricted license detected
license_finder --decisions-file=approved_licenses.yml || exit 1
# Trivy — license scanning built-in
trivy image --scanners license nginx:1.25
trivy repo --scanners license --ignored-licenses MIT,Apache-2.0 .
# sbom-scorecard — SBOM quality + policy scoring
go install github.com/eBay/sbom-scorecard@latest
sbom-scorecard score sbom.cdx.json
# Reports: NTIA compliance, component completeness, has hashes, has licenses, etc.# Conftest (OPA) — SBOM policy-as-code# policy/sbom.rego:
package sbom
deny[msg] {
component := input.components[_]
component.licenses[_].expression == "GPL-3.0-only"
msg := sprintf("GPL-3.0 detected in component: %v", [component.name])
}
conftest test sbom.cdx.json --policy policy/
🔧
Tooling Reference
// The supply chain security toolchain
SBOM Generation
🔬
Syft
anchore/syft · github.com/anchore/syft
Universal SBOM generator for container images, filesystems, and source repos. Outputs SPDX, CycloneDX, and custom formats. Best-in-class OCI attestation support. Pairs with Grype for vulnerability scanning.
CycloneDX-native SBOM generator with deep multi-language support. Handles 20+ build systems. Particularly strong for Java/Gradle and complex monorepos. Generates ML model BOMs (mlbom) for AI/ML projects.
Vulnerability Scanning
🦷
Grype
anchore/grype · github.com/anchore/grype
Fast, offline-capable vulnerability scanner. Accepts container images, SBOMs (SPDX/CycloneDX), directories, and more. Integrates with VEX for suppression. Same ecosystem as Syft.
Google's open-source scanner backed by OSV database. Scans lockfiles across 15+ ecosystems and SBOMs. Excellent false-positive rate. Can output CycloneDX for pipeline consumption.
Signing & Provenance
🔑
Cosign
sigstore/cosign · docs.sigstore.dev
The primary Sigstore CLI. Signs and verifies OCI images, blobs, and SBOM attestations. Keyless OIDC signing for CI/CD environments. Signatures stored in OCI registries alongside artifacts.
🏛
slsa-github-generator
slsa-framework/slsa-github-generator
Reusable GitHub Actions workflows for generating SLSA Level 3 provenance for Go binaries, generic artifacts, and container images. Provenance signed by GitHub's OIDC, stored in Rekor.
Policy & Detection
🧲
Socket
socket.dev · @socketsecurity/cli
Behavioral malicious-package detection for npm, PyPI, Go, and Rust — catches zero-day supply chain attacks that traditional CVE-based scanning misses because most malicious packages never get a CVE. Tracked 1,700+ packages tied to a single North Korea-linked campaign in H1 2025 alone. Intercepts install commands and provides PR-level GitHub app scanning.
🐕
guarddog
DataDog/guarddog · github.com/DataDog/guarddog
Datadog's malicious package detector. 20+ heuristics covering typosquatting, install scripts, exfiltration patterns, obfuscation. Works on PyPI and npm. Integrates cleanly into CI pipelines.
🎯
Endor Labs / Snyk (reachability analysis)
endorlabs.com · snyk.io
Adds a second filter on top of CVE and malicious-package scanning: does your code actually call the vulnerable function? Reachability analysis cuts through alert fatigue on transitive dependencies, where most vulnerable code lives but most of it is never executed.