Supply-chain attacks on AI and LLM tooling, and how to defend
Poisoned packages, images and CI actions hit AI tooling in 2026. The shared pattern, the dated facts and the checks to run on your own app project.
Published Last updated
Supply-chain attacks on AI tooling follow one pattern: an attacker gets control of how a package or image is published, and the poisoned release runs wherever you install it, next to your keys. To defend, pin exact versions with hashes or digests, delay brand-new releases, keep publishing tokens short-lived, and treat any package an AI tool suggests as unknown until you have looked it up.
What is the pattern behind these attacks?
Each incident below travelled through a path the victims already trusted: a maintainer's token, a release workflow, a moving tag, or a package name that a model made up. Dates come from the primary sources.
| Incident | Date | What was poisoned | How it ran | Source |
|---|---|---|---|---|
| Trivy GitHub Action | March 19 to 20, 2026 | 76 of 77 trivy-action version tags, all setup-trivy tags | Inside CI jobs that referenced a tag | GHSA-69fq-xp46-6x23 |
| LiteLLM and Telnyx on PyPI | March 2026 | Malicious releases after an API token exposure traced to an exploited Trivy dependency | At install. LiteLLM was live 2 hours 32 minutes, 119,000+ downloads | PyPI blog |
| ChainDrop | August 4, 2026 | 400+ npm packages from unrelated publishers | A preinstall script that took npm, GitHub and AWS credentials and spread | Microsoft |
| LiteLLM 1.107.0 | October 21, 2026 | PyPI wheels, Docker Hub and GHCR tags | At every Python start, even if litellm was never imported | LiteLLM, Datadog |
| react-codeshift | January 14, 2026 | A package name a model invented, referenced by 237 repositories | When an agent ran the install command in a skill file | Aikido |
| postmark-mcp | September 25, 2025 | An npm MCP server, from 1.0.16 onward | Added a hidden BCC to every email the agent sent | Snyk |
Datadog states that no connection between the two LiteLLM incidents has been established. OWASP lists the class as LLM03:2025 Supply Chain.
What happened with LiteLLM on October 21, 2026?
LiteLLM is an open-source gateway that many teams put in front of their model providers. Everything below is the maintainer's own account, last updated October 21 at 20:30 UTC and marked "incident contained, investigation in progress" at our check on October 24, 2026.
- Cause: three developers' GitHub CLI credentials were abused, branch protection was overridden, and a release workflow was pointed at a lookalike repository,
Berri-AI/litellminstead ofBerriAI/litellm. - PyPI:
litellm==1.107.0was live from 11:39:51 to 13:23 UTC. - Docker Hub: the tags
v1.107.0,latest,main-latestandmain-stableresolved to the bad image from 11:46:56 to 14:20 UTC. GHCR tags were affected until 13:51 UTC. - Scope: version 1.107.0 only. Earlier versions and the private Enterprise release were reported as unaffected.
- Open question: how the attackers first got in is not confirmed. The maintainer says a coding tool's GitHub token appeared in logs of an exposed internal deployment, and it does not call that the proven entry point.
Reading these facts
These are vendor-claimed findings. Datadog's separate write-up describes the same startup files and a similar release window. The maintainer also says an embargoed enterprise release fixes a separate vulnerability, with disclosure scheduled for October 27, 2026. Recheck the report before you act on a detail.
Why does AI tooling raise the stakes?
A model gateway or agent host holds many keys in one place. Datadog lists what the LiteLLM malware went after: cloud credentials, SSH and Git tokens, LLM API keys and coding assistant sessions. The maintainer's rotation list includes every provider key stored in the proxy database, its master and virtual keys, and the database password.
- Code runs without being imported. The LiteLLM files run when Python starts, so a package you installed and never used still ran. Flags that turn off install scripts do not help here.
- Skill files act like instructions. Aikido found agents running the install command a generated skill file contained, and the package behind the name did not exist.
- Local tools run with your rights. The MCP security guidance says a local MCP server can run any command the client can, and that clients should show the exact command before starting one.
Where can this reach my own app project?
If you download your project code or connect your own repository, these files are yours to read. Look in five places.
- App dependencies:
package.jsonand the lockfile. Look for ranges such as^with no committed lockfile. - CI workflows: lines in
.github/workflowsthat sayuses: owner/action@v1. A tag can be moved, as the Trivy advisory shows. Red's page on fake security-audit workflows covers a related GitHub Actions campaign. - Server code and images:
requirements.txt, and DockerfileFROMlines ending in:latest. - Agent tooling: the MCP server list in your coding tool and any skill file that runs
npxorpip. - Keys within reach: every
.envfile and CI secret. In Expo, a variable that starts withEXPO_PUBLIC_is written into the app bundle, so an AI provider key never belongs there. AI inside your app uses credits, which a leaked key can spend for a stranger.
Related: the 15-minute app check, the chatbot self-test and the security hub.
What defends each place?
| Control | What to look for | What it stops | What it leaves open |
|---|---|---|---|
| Exact pins with hashes | --require-hashes in pip. In npm, npm ci in CI, which fails when the lock and manifest disagree | A floating range quietly pulling a new bad release | A bad version you pinned yourself |
| Release cooldown | npm min-release-age, in days. Default is unset | Short windows. PyPI suggests about three days, and 1.107.0 was live about two hours on PyPI | A bad release that stays unnoticed for longer than the delay |
| Install scripts off | npm 12 makes dependency scripts opt-in. On older npm, ignore-scripts defaults to false | Install-time droppers such as ChainDrop's preinstall step | Code that runs at Python start or at import |
| Actions pinned to a commit SHA | A 40-character hash after @, as GitHub recommends, and a read-only default token | A moved tag, as in the Trivy case | A bad commit you chose, and secrets given to the job |
| Images by digest | image@sha256:..., since tags can be reassigned and digests cannot | A repointed latest | A digest taken after the image was already bad |
| Short-lived publishing | If you publish packages, Trusted Publishing with tokens that expire after 15 minutes | A stolen release token that works until someone notices | A taken-over CI workflow that publishes in that window |
| Reviewed agent tools | Exact start command, pinned version, and for HTTP servers a token audience check | Surprise installs and hidden behaviour such as the BCC | A later update that changes behaviour after your review |
What do I do if a bad version ran on my machine?
Order matters, because a key typed on an infected machine leaks again. This follows the LiteLLM report and Datadog's advice; other incidents have their own vendor lists.
- Find out. Run
pip show litellmand compare image digests with the report. Finding the named files confirms exposure. Not finding them leaves the question unknown. - Stop Python from starting on that host until the startup files are removed, remove them, and end the background process the report names.
- Rebuild the environment or container from scratch and pin version 1.106.2 or another release you have checked.
- From a different machine, rotate the host's cloud role, every provider key, the gateway keys and the database password. Red's rotation guide has the general order.
- Read your cloud and provider logs for use of those keys from places you do not recognise, starting from the install time.
For the wider October picture, including Railway, Zeabur and TiDB Cloud, see Red's October 2026 security tracker and the ChainDrop check.
Where do you stand?
Mark each item. Everything starts as unknown, because an unchecked item is unknown. Move one to confirmed only when you hold the evidence listed under it.
Your supply-chain check
- Detected: You found the problem.
- Unknown: Not checked yet, or the check could not tell.
- Confirmed by owner evidence: You checked and kept the proof.
Your answers stay in this browser tab. Nothing is saved or sent.
Frequently asked questions
Is LiteLLM 1.107.0 the only affected version?
According to the maintainer's report of October 21, 2026, yes, within the stated time windows. Earlier versions and the private Enterprise release were reported as unaffected. The report was still marked investigation in progress at our check on October 24, 2026, so read it again before you rely on this answer.
I uninstalled the package. Is the problem gone?
Not necessarily. Datadog's analysis says the files that run at Python start stay in site-packages after an uninstall. If 1.107.0 ever ran on a machine, follow the maintainer's cleanup, rebuild the environment, and rotate secrets from a different machine.
Does a poisoned package reach my users' phones?
The incidents on this page ran where packages are installed or started: laptops, CI runners, servers and containers, which is where the keys were. If you built an app release while a poisoned dependency was installed, pin a known good version, rebuild and release an update.
What is slopsquatting?
It is registering a package name that an AI model invented, so the next person or agent who runs the install command gets the attacker's code. Aikido documented a case in January 2026 where 237 repositories already pointed at an unpublished name that came from generated agent skill files.
Should I stop using MCP servers and agent skills?
There is no general answer. Treat each one as code that runs with your privileges. Read the start command, pin the version, give it only the keys it needs, and check that any package name it installs exists and belongs to the publisher you expect.
Can the red.run.cloud scan see any of this?
Only part of it. The scans work from outside your live site, so they cannot read your lockfile, CI workflows or laptop. They can show readable .env and .git paths and keys in shipped bundles. Everything else on this page stays unknown until you check it.
Sources
Checked October 24, 2026. Vendor statements are labelled as the vendor's own.
- Security incident, October 21, 2026, LiteLLM
- LiteLLM 1.107.0 supply chain compromise, Datadog Security Labs
- Incident report: LiteLLM and Telnyx supply chain attack, Python Package Index blog, April 2, 2026
- GHSA-69fq-xp46-6x23 (CVE-2026-33634), Trivy supply chain, Aqua Security on GitHub
- ChainDrop supply chain compromise, August 4, 2026, Microsoft Security Blog
- Slopsquatting via hallucinated agent skills, Aikido Security
- Malicious postmark-mcp package on npm, Snyk
- Authorization, specification 2026-07-28, Model Context Protocol
- Security best practices, local MCP server compromise, Model Context Protocol
- Security hardening for GitHub Actions, GitHub Docs
- Secure installs and hash-checking mode, pip documentation
- Trusted Publishing, PyPI documentation
- npm ci, npm documentation
- npm config: min-release-age and ignore-scripts, npm documentation
- npm install-time security changes, July 8, 2026, GitHub Changelog
- Tags and digests, Docker documentation
- LLM03:2025 Supply Chain, OWASP GenAI Security Project
- Environment variables in Expo, Expo docs
