Skip to content
All posts

LiteLLM Supply Chain Attack: What Happened, What to Do

November 9, 2026 · PlayCISO
TL;DR · the short version

LiteLLM says two releases of its Python package, 1.82.7 and 1.82.8, were published to PyPI on 24 March 2026 with a credential stealer and were removed after PyPI quarantined them. LiteLLM says the attacker bypassed its CI/CD workflows and that the incident may be linked to the Trivy compromise. FutureSearch found it when a fork bomb in the malware crashed a machine. Snyk and press reports attribute the campaign to a group called TeamPCP; LiteLLM does not name an attacker. This page gives the confirmed facts, where sources differ, the indicators and a response checklist.

Put it into practice
Check your AI dependencies for risky packages
Review the AI libraries your projects pull in, the kind of unpinned transitive dependency this attack relied on.
Open the AI dependency scanner

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.

Useful next, if this was relevant to you

Showing 1 of 3: Breach Cost Calculator

Timeline (UTC)

Times are as each source gives them. Where they conflict, both are shown.

Date and time (2026)EventSource
Late FebSnyk says a “Pwn Request” against Trivy’s CI (GHSA-9p44-j4g5-cfx5) stole aqua-bot credentialsSnyk
19 Mar, 17:43Trivy GitHub Action v0.69.4 tags rewritten to point at a malicious releaseSnyk
24 Mar, 10:39litellm 1.82.7 published to PyPI. LiteLLM gives 10:39 as the start of the exposure windowLiteLLM, Snyk
24 Mar, 10:52litellm 1.82.8 published to PyPI, adding the .pth fileSnyk, FutureSearch
24 Mar, 11:48Disclosure issue #24512 opened on GitHub (Snyk lists it under FutureSearch)Snyk
24 Mar, about 12:301.82.7 also reported compromisedFutureSearch, GitHub issue #24512
24 Mar, about 12:44 to 12:46Snyk 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:38PyPI quarantines the package (Snyk). LiteLLM says the versions were live “about 40 minutes”, which does not match this timeSnyk, LiteLLM
24 Mar, 13:48Clean tracking issue #24518 openedSnyk
24 Mar, 15:09A LiteLLM maintainer confirms GitHub, Docker and PyPI keys rotatedSnyk
24 Mar, 15:27Compromised versions deleted (Snyk). FutureSearch instead says the versions were yanked and the quarantine lifted at 20:15Snyk, FutureSearch
24 Mar, 16:00End of the window in which LiteLLM says installs may be affectedLiteLLM
26 MarLiteLLM adds checkmarx[.]zone to its indicatorsLiteLLM
30 MarClean v1.83.0 released through a new CI/CD v2 pipelineLiteLLM

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.

TypeValueSource
Filelitellm_init.pth in site-packagesLiteLLM
Domain (exfiltration)models.litellm[.]cloudLiteLLM
Domain (C2 polling)checkmarx[.]zoneLiteLLM
SHA-256, litellm_init.pth (1.82.8)71e35aef03099cd1f2d6446734273025a163597de93912df321ef118bf135238Snyk
SHA-256, proxy_server.py (1.82.7)a0d229be8efcb2f9135e2ad55ba275b76ddcfeb55fa4370e0a522a5bdee0120bSnyk
SHA-256, sysmon.py6cf223aea68b0e8031ff68251e30b6017a0513fe152e235c26f248ba1e15c92aSnyk
Path~/.config/sysmon/sysmon.py, /root/.config/sysmon/sysmon.py, ~/.config/systemd/user/sysmon.serviceSnyk, FutureSearch
Path/tmp/tpcp.tar.gz, /tmp/session.key, /tmp/payload.enc, /tmp/session.key.enc, /tmp/.pg_state, /tmp/pglogSnyk
KubernetesPods node-setup-{node_name} in kube-system, container setup, image alpine:latestSnyk

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 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

  1. 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
  2. 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 helps you sequence it.
  3. 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.
  4. 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 is a starting point.
  5. 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.
  6. Practise the scenario. The Agent Plugin Supply Chain Lab and 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.

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

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.

Check your AI dependencies for risky packages
Review the AI libraries your projects pull in, the kind of unpinned transitive dependency this attack relied on.
Open the AI dependency scanner

Ready to practise the decisions these articles describe?

Run your first Cyber War Room free →

Pro

🖤 Black Friday: new customers get 3 months of Pro for $5, then $5/month. Ends 30 Nov. Claim 3 months for $5 →