--- title: "LiteLLM Supply Chain Attack: What Happened, What to Do" url: https://playciso.com/blog/litellm-supply-chain-attack-2026 updated: 2026-11-09 section: Blog publisher: PlayCISO --- # LiteLLM Supply Chain Attack: What Happened, What to Do > LiteLLM 1.82.7 and 1.82.8 on PyPI carried a credential stealer on 24 March 2026. Confirmed vs claimed, timeline, indicators and what to do now. Source: https://playciso.com/blog/litellm-supply-chain-attack-2026 · Published: 2026-11-09 · Publisher: PlayCISO (https://playciso.com) Primary source: https://docs.litellm.ai/blog/security-update-march-2026 --- On 24 March 2026, **two versions of LiteLLM, the open-source Python gateway for calling many AI model providers, were published to PyPI with a credential stealer inside**. LiteLLM’s own security update names them as `litellm==1.82.7` and `litellm==1.82.8`, says they went up at 10:39 UTC and were quarantined by PyPI, and says the attacker “bypassed official CI/CD workflows and uploaded malicious packages directly to PyPI”. LiteLLM does not name an attacker. Snyk and press reports attribute the campaign to a group called TeamPCP; that is a researcher assessment, not a maintainer finding. If a build or machine installed either version, treat the secrets on it as exposed. ## Confirmed vs not yet known - LiteLLM states: versions 1.82.7 and 1.82.8 were malicious; the payload was a credential stealer; the packages were removed from PyPI; maintainer credentials were rotated; Google’s Mandiant was engaged for forensic analysis; and “no malicious code was pushed to main”. - LiteLLM says, with hedging: a maintainer’s PyPI account “may have been compromised” and the incident “may be linked to” the broader Trivy compromise, with stolen credentials “reportedly used” to reach the publishing pipeline. - Claimed by researchers, not by LiteLLM: that the actor is TeamPCP (Snyk, IT Pro: “believed”), and the detail of how a Trivy compromise yielded the PyPI publishing token (Snyk). - Sources differ: how long the versions were live and when they were quarantined or removed (see the timeline). - Not found in any primary source: a count of downloads or affected organisations. Some third-party posts print figures; we could not trace them to a primary source, so we do not repeat them. ## What was compromised - Package and registry: litellm on PyPI, versions 1.82.7 and 1.82.8 (LiteLLM). - 1.82.7: a malicious payload in proxy_server.py (LiteLLM). Snyk says it is a base64 payload in litellm/proxy/proxy_server.py that runs when litellm.proxy is imported. - 1.82.8: the same payload plus litellm_init.pth (LiteLLM). A .pth file in site-packages runs on every Python interpreter start, so the code ran without anything importing LiteLLM (FutureSearch, Snyk). Snyk adds that the file is listed in the wheel’s RECORD, so hash checks against the wheel pass. - Not affected, per LiteLLM: LiteLLM Cloud users; users of the official ghcr.io/berriai/litellm Docker image, which pins dependencies in requirements.txt; users on 1.82.6 or earlier who did not upgrade in the window; users who installed from the GitHub source repository. - Possibly affected, per LiteLLM: anyone who ran an unpinned pip install litellm that resolved to either version, Docker images built in the window that way, and projects with an unpinned transitive dependency on LiteLLM (for example AI agent frameworks, MCP servers or orchestration tools). ## What the malicious code did LiteLLM describes it as a credential stealer that harvested environment variables, SSH keys, AWS, GCP and Azure credentials, Kubernetes tokens and database passwords, encrypted the data and sent it by POST to `models.litellm[.]cloud`, a domain LiteLLM says is “not an official BerriAI / LiteLLM domain”. Snyk and FutureSearch report more detail, which we attribute to them: - Collection (Snyk): SSH keys, .env files, Git and CI/CD configuration, cloud credentials and metadata endpoints, container and Kubernetes secrets, and cryptocurrency wallet files. FutureSearch lists shell history and .gitconfig as well. - Exfiltration (Snyk, FutureSearch): data encrypted with AES-256-CBC, the session key wrapped with a hardcoded 4096-bit RSA public key, bundled in an archive and POSTed out. - Persistence (Snyk): ~/.config/sysmon/sysmon.py and a systemd user service, which polls checkmarx[.]zone every 5 minutes and runs what it downloads. Snyk says that at analysis time the endpoint returned YouTube URLs rather than a payload. - Kubernetes (Snyk, FutureSearch): if a service account token is present, the code reads secrets across namespaces and tries to start privileged alpine:latest pods named node-setup-* on nodes in kube-system. ## How it was found FutureSearch says its team hit the problem when litellm was pulled in as a transitive dependency of an MCP plugin running in Cursor. The `.pth` launcher started a child Python process, and because `.pth` files run on every interpreter start, each child re-triggered it, a fork bomb that crashed the machine. FutureSearch writes: “The fork bomb is actually a bug in the malware.” The first public report on GitHub, issue #24512 in BerriAI/litellm, is titled “[Security]: CRITICAL: Malicious `litellm_init.pth` in litellm 1.82.8 — credential stealer” and was opened by the user @isfinne on 24 March. A commenter on that issue reported that 1.82.7 was also compromised, with the payload in `proxy/proxy_server.py` but no `.pth` file. Snyk’s timeline credits FutureSearch with opening the 11:48 UTC disclosure issue; the GitHub page shows a different opener, so we do not settle who filed first. ## Timeline (UTC) Times are as each source gives them. Where they conflict, both are shown. | Date and time (2026) | Event | Source | | --- | --- | --- | | Late Feb | Snyk says a “Pwn Request” against Trivy’s CI (GHSA-9p44-j4g5-cfx5) stole aqua-bot credentials | Snyk | | 19 Mar, 17:43 | Trivy GitHub Action v0.69.4 tags rewritten to point at a malicious release | Snyk | | 24 Mar, 10:39 | litellm 1.82.7 published to PyPI. LiteLLM gives 10:39 as the start of the exposure window | LiteLLM, Snyk | | 24 Mar, 10:52 | litellm 1.82.8 published to PyPI, adding the .pth file | Snyk, FutureSearch | | 24 Mar, 11:48 | Disclosure issue #24512 opened on GitHub (Snyk lists it under FutureSearch) | Snyk | | 24 Mar, about 12:30 | 1.82.7 also reported compromised | FutureSearch, GitHub issue #24512 | | 24 Mar, about 12:44 to 12:46 | Snyk says bot comments flooded issue #24512 and it was closed using a compromised maintainer account. FutureSearch instead gives 13:03 for the closure as “not planned” | Snyk, FutureSearch | | 24 Mar, about 13:38 | PyPI quarantines the package (Snyk). LiteLLM says the versions were live “about 40 minutes”, which does not match this time | Snyk, LiteLLM | | 24 Mar, 13:48 | Clean tracking issue #24518 opened | Snyk | | 24 Mar, 15:09 | A LiteLLM maintainer confirms GitHub, Docker and PyPI keys rotated | Snyk | | 24 Mar, 15:27 | Compromised versions deleted (Snyk). FutureSearch instead says the versions were yanked and the quarantine lifted at 20:15 | Snyk, FutureSearch | | 24 Mar, 16:00 | End of the window in which LiteLLM says installs may be affected | LiteLLM | | 26 Mar | LiteLLM adds checkmarx[.]zone to its indicators | LiteLLM | | 30 Mar | Clean v1.83.0 released through a new CI/CD v2 pipeline | LiteLLM | ## Indicators of compromise Domains and the file name are from LiteLLM; the hashes, paths and Kubernetes names are from Snyk, copied as published. LiteLLM lists no hashes for the malicious files. Treat a hit as a lead to investigate. | Type | Value | Source | | --- | --- | --- | | File | litellm_init.pth in site-packages | LiteLLM | | Domain (exfiltration) | models.litellm[.]cloud | LiteLLM | | Domain (C2 polling) | checkmarx[.]zone | LiteLLM | | SHA-256, litellm_init.pth (1.82.8) | 71e35aef03099cd1f2d6446734273025a163597de93912df321ef118bf135238 | Snyk | | SHA-256, proxy_server.py (1.82.7) | a0d229be8efcb2f9135e2ad55ba275b76ddcfeb55fa4370e0a522a5bdee0120b | Snyk | | SHA-256, sysmon.py | 6cf223aea68b0e8031ff68251e30b6017a0513fe152e235c26f248ba1e15c92a | Snyk | | Path | ~/.config/sysmon/sysmon.py, /root/.config/sysmon/sysmon.py, ~/.config/systemd/user/sysmon.service | Snyk, FutureSearch | | Path | /tmp/tpcp.tar.gz, /tmp/session.key, /tmp/payload.enc, /tmp/session.key.enc, /tmp/.pg_state, /tmp/pglog | Snyk | | Kubernetes | Pods node-setup-{node_name} in kube-system, container setup, image alpine:latest | Snyk | ## How the attacker got in: what is confirmed LiteLLM’s update says the team believes the incident “may be linked to” the Trivy compromise, that the Trivy dependency was part of its CI/CD security scanning workflow, and that stolen credentials were “reportedly used” to access the publishing pipeline. Snyk goes further: it says LiteLLM’s pipeline ran Trivy without a pinned version, and that the compromised scanner took the `PYPI_PUBLISH` token from the GitHub Actions runner, which the attacker then used to publish. We could not confirm that chain independently; treat it as Snyk’s reconstruction. Our [March 2026 recap](/blog/march-2026-cybersecurity-breaches-roundup) covers the wider Trivy-linked campaign. ## What LiteLLM says it did - Removed the compromised packages from PyPI and rotated maintainer credentials, with new authorised maintainers. - Engaged Google’s Mandiant for forensic analysis of the build and publishing chain. - Paused releases, then shipped v1.83.0 on 30 March through a CI/CD v2 pipeline with “isolated environments, stronger security gates, and safer release separation”. - Audited PyPI and Docker releases from v1.78.0 through v1.82.6 against SHA-256 digests and Git commits and lists them as clean, and says Docker images can be verified with cosign from v1.83.0-nightly. ## What security leaders should do this week - Find out whether you installed either version. LiteLLM advises checking local environments, CI/CD, Docker builds and deployment logs for installs between 10:39 and 16:00 UTC on 24 March 2026. Run the check below in every environment, including images you built yourself. # 1. Is either malicious version installed (run inside each virtualenv, container and CI image)? pip show litellm | grep -i '^Version' # Affected per LiteLLM: 1.82.7 and 1.82.8. LiteLLM names 1.83.0 as the clean release. # 2. Is the malicious startup file present? find / -name litellm_init.pth 2>/dev/null # 3. Persistence paths reported by Snyk and FutureSearch ls -l ~/.config/sysmon/sysmon.py /root/.config/sysmon/sysmon.py ~/.config/systemd/user/sysmon.service 2>/dev/null # 4. Kubernetes: pods reported by FutureSearch and Snyk kubectl get pods -n kube-system | grep node-setup - If you find either version, rotate everything that host could reach. LiteLLM’s list: API keys, cloud keys, database passwords, SSH keys, Kubernetes tokens and anything in environment variables or config files. Rebuild from a clean image rather than cleaning in place. Our [secret rotation order planner](/tools/secret-rotation-order-planner) helps you sequence it. - Remove litellm_init.pth, then hunt for persistence using the paths and Kubernetes names above, and look for outbound connections to the two domains in your proxy and DNS logs. - Pin and verify. LiteLLM recommends pinning to a verified release such as 1.82.6 or earlier or to 1.83.0. Pin exact versions with hashes in lockfiles, and check what your AI frameworks, MCP servers and agent plugins pull in transitively. The [AI dependency scanner](/tools/ai-dependency-scanner) is a starting point. - Treat your CI scanner as part of the supply chain. The reported entry point was a security tool run in CI without a pinned version. Pin actions to commit SHAs, keep publish tokens out of jobs that run third-party tools, and prefer short-lived publishing credentials. See [GitHub CI secret hardening](/tools/github-ci-secret-hardening). - Practise the scenario. The [Agent Plugin Supply Chain Lab](/tools/agent-plugin-supply-chain-lab) and [AI CLI Supply Chain Lab](/tools/ai-cli-supply-chain-lab) walk through a poisoned dependency reaching an AI tool. If LiteLLM sits between your agents and model providers, also read [malicious LLM routers and tool-call injection](/blog/malicious-llm-routers-tool-call-injection-defense). ## FAQ ### What was the LiteLLM supply chain attack? LiteLLM says malicious versions 1.82.7 and 1.82.8 of its litellm package were published to PyPI on 24 March 2026 and acted as a credential stealer. LiteLLM says the attacker bypassed its official CI/CD workflows and uploaded the packages directly to PyPI, and that a maintainer account may have been compromised. ### Which LiteLLM versions were malicious? litellm 1.82.7 and 1.82.8 on PyPI, per LiteLLM. Version 1.82.7 carried the payload in proxy_server.py. Version 1.82.8 carried the same payload plus a file named litellm_init.pth. LiteLLM says 1.82.6 and earlier are not affected, and names 1.83.0 (released 30 March 2026) as a clean release. ### Who was behind the LiteLLM attack? LiteLLM names no attacker. Snyk and press reports attribute the campaign to a group called TeamPCP, citing a shared RSA key (which Snyk says Wiz researchers confirmed), the tpcp.tar.gz file name and shared infrastructure. IT Pro words it as "believed". Treat the attribution as a researcher assessment, not a maintainer finding. ### How was the LiteLLM attack discovered? FutureSearch says it found it when litellm arrived as a transitive dependency of an MCP plugin running in Cursor. The malicious .pth file launched a child Python process that re-triggered itself on every interpreter start, a fork bomb that crashed the machine. FutureSearch says "The fork bomb is actually a bug in the malware." ### Is the official LiteLLM Docker image affected? LiteLLM says users of the official ghcr.io/berriai/litellm Docker image are not affected because it pins dependencies in requirements.txt. It also says LiteLLM Cloud users and people who installed from the GitHub source repository are not affected. Docker images you built yourself with an unpinned pip install litellm during the window may be. ### What does the malicious code do? LiteLLM says it harvested environment variables, SSH keys, AWS, GCP and Azure credentials, Kubernetes tokens and database passwords, encrypted them and sent them by POST to models.litellm.cloud, a domain LiteLLM says is not its own. Snyk and FutureSearch add a persistence service and, where a Kubernetes service account token exists, privileged pods in kube-system. ### What should I do if I installed litellm 1.82.7 or 1.82.8? Treat every secret on that host as exposed and rotate it: API keys, cloud keys, database passwords, SSH keys, Kubernetes tokens and anything in environment variables or config files. Remove litellm_init.pth, check for the persistence files reported by researchers, audit CI logs and Docker builds for the install window, and pin to a verified release. This is LiteLLM's own remediation list. ### How long were the malicious versions on PyPI? Sources differ. LiteLLM says "about 40 minutes" before PyPI quarantined them and advises anyone who installed or upgraded between 10:39 UTC and 16:00 UTC on 24 March to check. Snyk's timeline lists quarantine at about 13:38 UTC and deletion at 15:27 UTC, and says about three hours. FutureSearch says the versions were yanked and the quarantine lifted at 20:15 UTC. ## Sources - [LiteLLM: Security Update, March 2026](https://docs.litellm.ai/blog/security-update-march-2026) (published 24 March, updated 27 March), the primary source - [BerriAI/litellm issue #24512: Malicious litellm_init.pth in litellm 1.82.8](https://github.com/BerriAI/litellm/issues/24512) (first public report and maintainer replies) - [FutureSearch: litellm PyPI supply chain attack](https://futuresearch.ai/blog/litellm-pypi-supply-chain-attack/) (the team that found it; updated 30 March) - [Snyk: How a Poisoned Security Scanner Became the Key to Backdooring LiteLLM](https://snyk.io/articles/poisoned-security-scanner-backdooring-litellm) (timeline, indicator hashes, TeamPCP attribution) - [IT Pro: LiteLLM PyPI compromise, everything we know so far](https://www.itpro.com/security/litellm-pypi-compromise-everything-we-know-so-far) (26 March; attribution worded as “believed”) *This article is educational guidance for security leaders, not legal advice or a forensic report. Times differ between sources; check LiteLLM’s security update for the latest details.*