LiteLLM 1.107.0 Ran Malware on Python Startup: How to Recover

LiteLLM 1.107.0 poisoned official PyPI and container releases. Check the exact exposure window, rebuild safely and rotate every credential at risk.
Diagram of the malicious LiteLLM 1.107.0 package executing credential theft through Python startup hooks
The compromised LiteLLM package ran during Python startup and targeted developer, cloud, browser, SSH and proxy credentials. Image: Microsoft Security Research.

LiteLLM’s official 1.107.0 package and several official container tags were compromised on October 21, shipping a credential stealer that could run whenever Python started. The malicious code did not wait for an application to import LiteLLM.

A final root-cause report published October 23 traces the incident to an exposed master key that was identified in May but never revoked. The attacker used that key to obtain an organization owner’s GitHub CLI token, harvested two more maintainers’ tokens through CI workflows, redirected LiteLLM’s private release system to a lookalike repository, and used a stolen identity to approve the production release.

The compromised artifacts were publicly available for roughly two hours. That narrow window limits exposure, but it does not make cleanup a normal upgrade: any affected environment that started Python should be treated as compromised, with recovery performed from a known-clean system.

Exactly which LiteLLM artifacts were affected

LiteLLM identified one PyPI release and a set of mutable container tags:

  • PyPI: all seven wheels for litellm==1.107.0, available from 11:39:51 UTC until PyPI quarantined the release by 13:23 UTC on October 21.
  • Docker Hub: v1.107.0, latest, main-latest and main-stable while they pointed to compromised image index sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e, from 11:46:56 to 14:20 UTC.
  • GitHub Container Registry: the same four tags across the standard, database and non-root LiteLLM images, from 11:46:56 until the affected tags became unavailable by 13:51 UTC.

Previous open-source releases were not affected, according to the project. LiteLLM also said its separate private enterprise registry did not distribute the malicious release.

Organizations should check more than production gateways. Developer laptops, CI runners, test hosts, internal package mirrors, build caches, lock files and derived container images may all contain the poisoned wheel or image. A floating tag may no longer point to the malicious digest today, so current registry state is not proof that a workload never ran it.

Why starting Python was enough to execute the malware

The malicious wheels placed cook.pth, cook.py and sitecustomize.py into the Python environment’s library directory. Python processes executable import lines in .pth files during site initialization and then attempts to load sitecustomize. That gave the package two startup paths outside LiteLLM’s normal application directory.

Microsoft Security Research’s technical analysis found that cook.pth imported cook.py, which unpacked an embedded credential collector identified as PRIVCOLLECT. A separate Unix-oriented loader in sitecustomize.py detached into the background, read a GitHub-hosted file for a server address and could fetch and execute new Python code from a /codepy endpoint.

Researchers had not confirmed that the second-stage loader successfully retrieved code when they analyzed it. The mechanism was still re-armable, however, because the attacker could change the GitHub-hosted pointer without publishing another package.

This behavior changes the first response step. Do not run python, pip or a package-inspection command inside a suspect environment. Even installing an unrelated dependency could launch the payload again. Inspect disks, images and package metadata from a trusted host or offline tooling instead.

What the credential collector targeted

The collector searched much more broadly than model-provider API keys. Its target list included:

  • AWS, Azure and Google Cloud credentials, including attempts to reach instance metadata services;
  • environment variables and, on Linux, readable environments from other processes through /proc;
  • source-control, package-registry, CI/CD, Vault and infrastructure-tool configuration;
  • SSH, GPG and selected TLS private-key material;
  • Chromium-family and Firefox credential data, cookies and browsing history, subject to platform-specific decryption limits;
  • AI development-tool credentials, including tokens associated with Cursor and GitHub Copilot;
  • LiteLLM proxy database records, including selected credential and model-configuration fields.

On proxy deployments, the malware used DATABASE_URL and Prisma to query up to 500 records from each of two tables. The practical scope can therefore include provider keys stored behind the gateway, LiteLLM master and virtual keys, the database password, and any cloud or workload identity available to the host.

The collector encrypted results with a per-run AES key, wrapped that key with an embedded RSA public key, packaged the data in a gzip archive and attempted to send it to www[.]litellm[.]dev/healthcheck. A marker at /tmp/.pc_once_72129118c59f5636c0bb indicates that stolen data was sent, but its absence does not establish that exfiltration failed.

How to check and recover without retriggering the payload

  1. Isolate affected systems. Stop automation from restarting Python services and, where operationally safe, stop existing Python processes. Investigate from a clean workstation or forensic environment.
  2. Build a complete artifact inventory. Look for LiteLLM 1.107.0 in virtual environments, caches, internal mirrors, build outputs and software bills of materials. For containers, match immutable digests and deployment history rather than relying only on current tag values.
  3. Preserve evidence before rebuilding. Collect relevant filesystem, process, network, cloud audit and identity logs. Useful files include cook.pth, cook.py, sitecustomize.py, /tmp/remote_code_loader.lock and the exfiltration marker. Microsoft’s report publishes hashes for all seven malicious wheels and the startup files.
  4. Rebuild from verified artifacts. Recreate containers and virtual environments instead of deleting only the litellm package directory. The startup files were installed outside that directory. LiteLLM’s incident guidance recommends pinning 1.106.2 during recovery.
  5. Rotate every reachable secret from a clean machine. Include model-provider keys, LiteLLM master and virtual keys, DATABASE_URL, cloud and workload credentials, source-control and registry tokens, CI secrets, SSH and GPG keys, AI coding-tool tokens, and browser sessions available to the affected account.
  6. Revoke sessions as well as replacing passwords. Password or key rotation does not necessarily invalidate active OAuth tokens, browser sessions or application sessions.
  7. Hunt for post-exfiltration use. LiteLLM specifically recommends checking AWS CloudTrail for GetCallerIdentity near installation time and for later use of the same role credentials from outside the organization’s infrastructure. Apply equivalent checks in Azure, Google Cloud, source-control and model-provider logs.

LiteLLM’s response notice warns that any affected host with outbound internet access should be assumed to have completed exfiltration. Removing the package alone is not sufficient because the detached loader can survive in a running process and exposed credentials remain usable after the files are gone.

How the release controls were bypassed

The root-cause chain began on May 27, when a configuration file committed to the public LiteLLM-Labs/lite-harness repository exposed the master key for an experimental Agent Platform deployment. The commit was force-pushed away and the key was marked for revocation, but the revocation did not happen.

On October 10, the attacker used that key to query agent configurations and recover a GitHub CLI OAuth token tied to a LiteLLM organization owner. The token was neither a service-account credential nor narrowly scoped. It provided owner-level repository access after two-factor authentication.

The attacker then used short-lived branches and CI workflows to send repository secrets to an external endpoint. Those secrets included GitHub CLI tokens for two maintainers. On October 21, the owner token disabled branch protection and changed the private release workflow to build from Berri-AI/litellm, a lookalike fork distinguished from the legitimate BerriAI/litellm by one hyphen. A second stolen maintainer token approved the production gate.

The resulting wheels and images went through LiteLLM’s normal signing and publishing path. Provenance faithfully recorded the malicious fork as the source, according to Datadog Security Labs. Signing established which workflow produced the artifacts; it did not establish that the workflow had been pointed at the correct repository.

LiteLLM had also temporarily relaxed a physical-device approval restriction to allow any two engineers to trigger and approve releases during a period of frequent bug-fix publishing. The attacker already controlled multiple identities, so the two-person gate did not represent two independent trust domains.

What engineering teams should change after recovery

Pinning LiteLLM to a clean version addresses this release, but the incident exposes broader weaknesses in dependency and release controls.

  • Use hash-pinned lock files for Python dependencies and immutable digests for container deployment.
  • Verify the repository owner and exact source identity recorded in build provenance, not just the presence of a valid signature.
  • Quarantine new packages in an internal mirror before they reach developer, CI or production environments.
  • Keep release approvals bound to hardware-backed identities and separate those identities from ordinary developer tokens.
  • Use service accounts with the smallest practical repository scope instead of personal organization-owner tokens.
  • Revoke exposed secrets immediately, even when the public commit or log entry containing them has been removed.
  • Limit outbound access from build agents, AI gateways and developer environments so an unexpected package cannot freely reach arbitrary endpoints.

CERT-In’s October 23 advisory independently highlights the same credential-theft and remote-code execution risk. Datadog notes that this is the second LiteLLM supply-chain compromise disclosed in 2026, although no link between the incidents has been established. For teams using LiteLLM as a central AI gateway, the immediate priority is to determine whether 1.107.0 ever executed and to treat the answer as an identity and infrastructure incident, not merely a dependency rollback.

Previous Post
Diagram showing llm-d evolving from round-robin model serving to cache-aware routing, tiered KV cache and priority flow control

llm-d 1.0 Brings Agent-Aware Routing to Kubernetes AI Inference

Related Posts
Server racks in a data center used to illustrate enterprise networking and security systems

Cisco’s Twice-Monthly Patch Cadence Starts With Catalyst Center and ClamAV Fixes

Cisco’s first July security-advisory drop under its new twice-monthly cadence includes a Catalyst Center arbitrary-file-read flaw and seven ClamAV vulnerabilities affecting Cisco Secure Endpoint. The change gives network and security teams more predictability, but it also means Cisco infrastructure patch planning needs to become a standing operating rhythm, not a quarterly scramble.
Read More