LiteLLM 1.82.7 and 1.82.8 on PyPI backdoored in TeamPCP supply-chain attack

TeamPCP published malicious LiteLLM 1.82.7 and 1.82.8 to PyPI on 24 March 2026; 1.82.8 ran a stealer via a .pth file on every Python start. What to rotate.

TechLogHub Engineering Team
March 24, 2026
3 min read
0 views

Share Article

LiteLLM PyPI Package Compromised in TeamPCP Supply‑Chain Attack

On 24 March 2026, two malicious LiteLLM releases, 1.82.7 and 1.82.8, were published to PyPI with credentials stolen in the Trivy supply-chain attack. LiteLLM is a widely used Python gateway that gives many LLM providers one interface, and it often runs in environments holding every provider API key a company owns. Version 1.82.8 didn't even need to be imported: a .pth file ran the credential stealer every time Python started.

What happened

According to LiteLLM's incident post, the malicious packages appeared on PyPI at 10:39 UTC on 24 March 2026. They were uploaded directly, bypassing the project's CI/CD, and have no matching tags or commits on GitHub. Researcher-compiled timelines put 1.82.8 about 13 minutes after 1.82.7. PyPI quarantined the project within hours, and LiteLLM gives the exposure window for pip users as 10:39 to 16:00 UTC.

LiteLLM believes the compromise came from the Trivy scanner in its CI security-scanning workflow. That ties it to TeamPCP's attack on Aqua Security's Trivy releases a few days earlier, which harvested publishing secrets from CI runners. The two versions behave differently:

  • 1.82.7: payload injected into litellm/proxy/proxy_server.py. It runs when the proxy module is imported.
  • 1.82.8: adds litellm_init.pth to site-packages. Python's site module executes import lines in .pth files at interpreter startup, so the payload ran in every Python process in that environment, including pip itself, test runners and unrelated scripts.

The double base64-encoded payload collected environment variables, SSH keys, AWS/GCP/Azure credentials, Kubernetes tokens, database passwords and other secrets. It encrypted them and POSTed them to models.litellm[.]cloud, a lookalike domain not owned by BerriAI. Endor Labs and others reported that it also tried to deploy privileged pods across Kubernetes clusters and installed a systemd-based backdoor at ~/.config/sysmon/sysmon.py. LiteLLM brought in Google's Mandiant, rotated maintainer credentials, and on 30 March shipped a clean v1.83.0 from a rebuilt CI/CD pipeline. From v1.83.0-nightly onward, GHCR images are signed with cosign.

Who is affected

  • Anyone who ran pip install litellm or an upgrade without a pinned version on 24 March 2026 between 10:39 and 16:00 UTC.
  • Docker images built in that window with an unpinned litellm install.
  • Projects that pull LiteLLM in transitively, through agent frameworks, MCP servers or orchestration tools, without a lockfile.
  • Not affected: users of the official ghcr.io/berriai/litellm proxy image (dependencies are pinned), LiteLLM Cloud, installs from GitHub source, and anyone who stayed on 1.82.6 or earlier.

What it means for developers and engineering teams

The .pth technique deserves attention from every Python team. Most people think a malicious dependency is harmless until it's imported. With a .pth file, installing the package is enough: any later python invocation in that environment runs the attacker's code. Pinning in requirements.txt protects you only if every path into the environment, including transitive dependencies, respects it. A lockfile with hashes does. A loose litellm>=1.80 doesn't.

LLM gateways are a high-value target because they combine credentials by design: provider keys for OpenAI, Anthropic and Google, cloud credentials for Bedrock or Vertex, and often database URLs for logging. Combine that with CI runners that hold PyPI publish tokens, and one poisoned scanner lets an attacker go from a security tool to an AI library to thousands of production environments in five days.

What to do now

  1. Check versions: pip show litellm in every environment, image and CI cache. Search lockfiles for 1.82.7 or 1.82.8.
  2. Look for the dropper: find / -name 'litellm_init.pth' 2>/dev/null. Also check for ~/.config/sysmon/sysmon.py, /tmp/pglog and /tmp/.pg_state.
  3. If found, rotate everything that environment could read: LLM provider keys, cloud credentials, database passwords, SSH keys, Kubernetes tokens and anything in .env files. Rebuild the host or image instead of cleaning it.
  4. Check network logs for traffic to models.litellm[.]cloud and checkmarx[.]zone.
  5. Pin with hashes: use uv lock, pip-compile --generate-hashes or Poetry lockfiles, and install with --require-hashes.
  6. Move to LiteLLM 1.83.0 or later, or stay on a verified release no newer than 1.82.6.
  7. If you maintain packages, switch to PyPI Trusted Publishing (OIDC) so CI holds no long-lived upload token, and keep scanners out of jobs that can publish.

Related on TechLogHub

Sources

Stay Updated

Get the next deep dive in your inbox

Subscribe for product analysis, engineering explainers, and practical guides published on TechLogHub.

See what launched this week

One email a week: new and trending developer tools, fresh comparisons, and what shipped. Unsubscribe in one click.