LiteLLM 1.107.0 Supply-Chain Compromise: Attack Chain, Payload and What CISOs Must Rotate

CISO Platform Intelligence · Software Supply Chain · AI Security · Updated Oct 29, 2026

TL;DR

  • On 21 October 2026, attackers used stolen maintainer tokens to run LiteLLM's own release pipeline. It published litellm==1.107.0 (all seven wheels) to PyPI, plus Docker Hub and GHCR images under v1.107.0, latest, main-latest and main-stable. LiteLLM says the artifacts were live for about two hours.
  • The package dropped cook.pth, cook.py and sitecustomize.py into site-packages, so the payload ran on every Python start, even if nothing imported LiteLLM. It stole browser, cloud, CI, developer and AI-tool credentials; on LiteLLM proxy hosts it also read the database tables holding upstream provider keys. It installed an hourly remote-code loader as well.
  • LiteLLM's root cause analysis traces it to an admin key committed to a public repo on 27 May. The commit was removed but the key was never revoked. Uninstalling is not enough: rebuild affected environments and rotate every credential the host could reach.

What happened (timeline, UTC)

When Event
27 May 2026 An administrative key for the internal LiteLLM Agent Platform is committed to a public repo. A follow-up commit removes the file about three hours later, but the original commit stays in public history until 22 Oct and the key is never revoked.
10 Oct The attacker calls the Agent Platform API with the key. The response returns an org owner's GitHub CLI OAuth token. Throwaway ci-tmp-* workflows send repo secrets, including other maintainers' tokens, to webhook.site, and the run records are deleted.
12 Oct A second round of workflows exfiltrates secrets from private repos.
13–18 Oct Per StepSecurity: litellm.dev is registered, the letters9813 GitHub account is created, and a dead-drop repo is set up.
19 Oct (StepSecurity; LiteLLM says "earlier that week") The release gate is relaxed so any two engineers can approve a release. Previously approval needed a special account locked to a physical office device.
21 Oct 10:08 The owner token overrides branch protection on the release workflow repo.
21 Oct 10:46–11:11 A release is built from the lookalike fork Berri-AI/litellm; the production gate is approved with a second maintainer's token.
21 Oct 11:39–11:46 Seven 1.107.0 wheels published to PyPI; Docker Hub and GHCR images published.
21 Oct 11:53 Workflow run records deleted with a third maintainer's token.
21 Oct 12:06 An Upwind Security researcher publicly reports the compromise (GitHub issue #47826).
21 Oct ~13:20–14:20 PyPI quarantines 1.107.0 (Datadog: 13:20; LiteLLM: by 13:23). GHCR tags made unavailable and Docker Hub tags removed or repointed (Datadog: 13:53; LiteLLM: 14:20 for Docker Hub).
21 Oct 16:20–17:01 Per StepSecurity, stolen AWS instance-role credentials are used from external IPs.
23 Oct LiteLLM publishes its root cause analysis.
24–25 Oct Clean releases resume (v1.106.3, v1.106.4 and backports).

Technical analysis

Distribution: official channels (PyPI, Docker Hub, GHCR), built by the project's real release workflow. StepSecurity says ten attacker commits in the fork added the payload, plus a data = "cook" line under [tool.maturin]. Datadog notes the artifacts carried build provenance naming the malicious fork as the source: provenance existed, but only helped if someone checked which repository it named.

Persistence and execution: Python runs .pth files and sitecustomize.py automatically at every interpreter start, so any Python process in the environment ran the payload, including pip.

Second stage: sitecustomize.py forks a daemon that, every hour, reads a hostname from a GitHub-hosted file, downloads code from that host and runs it. The file held only test or empty values, so no second stage was observed. On Windows the loader fails, but the stealer still runs.

What was stolen (StepSecurity's analysis of 16 modules):

  • Browsers: saved passwords and cookies. SSH and GPG keys; TLS and key files.
  • Cloud and registry credentials: AWS, Azure, gcloud, kubeconfig, Docker, GitHub CLI, npm, PyPI. Cloud instance metadata (AWS IMDS and ECS, GCP, Azure).
  • CI and infrastructure secrets: Vault, Terraform, Kubernetes. Process environments from /proc/*/environ; .env files; shell and database history.
  • Credentials for roughly 25 AI coding assistants.
  • On proxy hosts with DATABASE_URL set: the credentials and model tables holding upstream provider API keys.

Data was encrypted with AES-256 and RSA-4096 and sent by plain HTTP POST to http://www.litellm[.]dev/healthcheck. If the upload failed, the stealer retried on every start.

Affected artifacts: PyPI litellm==1.107.0 (StepSecurity says the sdist had a tampered build config but no payload). Images tagged v1.107.0, latest, main-latest and main-stable during the exposure window.

Selected indicators (as published by Datadog/StepSecurity): domain litellm[.]dev; dead drop raw.githubusercontent[.]com/letters9813/pythonclient-test/main/domain.txt; host files /tmp/.pc_once_72129118c59f5636c0bb and /tmp/remote_code_loader.lock; IPs 69.48.229[.]143 and 199.91.221[.]39. Full wheel and image hashes are in the Datadog and StepSecurity posts.

Why it happened

  • The leaked key was removed from the repo but never revoked. LiteLLM attributes this to human error.
  • The Agent Platform stored an org owner's GitHub CLI OAuth token rather than a scoped token. LiteLLM says such tokens are unscoped and not subject to GitHub's sensitive-action 2FA re-authentication.
  • The release approval control had been relaxed days before the attack.
  • The attacker used different stolen tokens for different steps; LiteLLM believes this was to avoid noisy audit logs.

Where sources disagree: LiteLLM's first incident post suspected the tokens came from internal deployment logs; its 23 October analysis revised this to the Agent Platform API response. Datadog's write-up says the initial token theft was not yet known.

Who is affected

Any host, CI runner or container that installed litellm==1.107.0 or pulled one of the floating image tags during the window, including indirect installs through a dependency that did not pin its version. Mirrors and caching proxies may still hold the artifacts. How many organisations installed it, the full scope of victims and attribution are not publicly known. StepSecurity reports misuse of stolen AWS credentials.

How it affects CISOs

AI gateways concentrate high-value secrets in one place: provider API keys, cloud roles and proxy databases. This payload specifically targeted the gateway's own credential store and developers' AI coding tools. Three lessons: "official channel" plus "provenance present" does not mean safe; floating tags like latest turn a two-hour window into automatic exposure; a secret that is removed but not revoked is still exposed.

What to do

Immediate (24h), per Datadog and StepSecurity guidance

  • Search lockfiles, environments and images for 1.107.0 and the affected tags; compare digests with published hashes.
  • On affected hosts, kill the process holding /tmp/remote_code_loader.lock before running any Python, then delete the three payload files and their __pycache__ entries.
  • Assume exfiltration succeeded on any host with outbound access. A missing marker file does not prove otherwise.
  • From a clean machine, rotate everything those hosts could reach: cloud keys and role sessions, SSH and GPG keys, browser credentials, registry, Kubernetes, Vault and CI tokens, AI tool tokens. On proxy hosts, also rotate every provider key in the database, the master and salt keys, and the DATABASE_URL password.
  • Block litellm[.]dev at DNS and egress. Search network logs for /codepy requests; a hit means attacker code likely ran.

This week

  • Rebuild environments and images from scratch rather than cleaning in place. Pin a clean version (1.106.4 or a backport) and pin images by digest.
  • Remove 1.107.0 from mirrors and internal registries.
  • Look for misuse of exposed credentials. In AWS, check CloudTrail for GetCallerIdentity calls and instance-role use from outside your infrastructure.
  • Update cosign verification: images from v1.106.3 onward are signed with a new key.

Strategic (standard practice, not incident-specific guidance)

  • No floating tags in production; enforce pinned versions with hashes. Add a cooling-off period before admitting new releases of critical packages.
  • Verify provenance names the expected source repository, not just that provenance exists.
  • Make revocation, not deletion, the closing step for any leaked secret. Scope CI and release tokens narrowly.
  • Limit what AI gateway hosts can reach, including instance metadata.

Questions to ask your team / vendors

  • Where do we run LiteLLM, directly or as a dependency, and do we pin by hash or digest?
  • Did anything pull latest or main-stable on 21 October?
  • Which secrets sit in our AI gateway database, and how fast can we rotate all of them?
  • When a secret leak is "fixed", does our process require proof of revocation?
  • Do our release pipelines depend on unscoped, user-bound CLI tokens? Do our provenance checks validate the source repository?
  • Vendors: do you embed LiteLLM, which version did you ship, and what did you rotate?

Sources

Discuss: Have you banned floating container tags and unpinned AI SDKs in production? How do you enforce that for vendor-embedded AI components?


Running AI gateways or LLM tooling in production?

CISO Platform members are sharing how they pin AI dependencies, scope gateway secrets and run rotation drills. Join to compare your AI supply-chain controls with peers who run the same stack.

Join CISO Platform (free for security leaders) →

Related on CISO Platform

★
★
★
★
★
Votes: 0
E-mail me when people leave their comments –

You need to be a member of CISO Platform to add comments!

Join CISO Platform

Join The Community Discussion