LiteLLM 1.107.0 contained malware that could run at Python startup, even when an application never imported LiteLLM. Developers who installed an affected wheel or deployed the compromised Docker image should isolate potentially exposed environments before running further Python-based checks.
According to JFrog Security Research, all seven PyPI wheels for the release carried a credential stealer and a remote-code loader. The official litellm/litellm:1.107.0 Docker image was also affected. The payload targeted AI-provider credentials, cloud access, SSH keys, Kubernetes tokens, browser data, and CI/CD secrets.
Status recorded in JFrogâs October 21, 2026 report: PyPI had removed the compromised release, and Docker Hub had removed the affected image and tags. Those removals stop neither malware already deployed nor the use of credentials already stolen.
This is a separate incident from LiteLLMâs March 2026 compromise. Crucially, the October payload appeared in built wheels but not in the published source archive, so reviewing a Git tag alone would not have exposed it.
Check Deployed Artifacts, Including Mutable Docker Tags
The affected release is LiteLLM 1.107.0. JFrog found the payload across all seven published wheels, covering macOS, Linux, musl Linux, and Windows targets.
For Docker deployments, checking whether a configuration explicitly names 1.107.0 is insufficient. JFrog says systems that pulled latest, main-latest, or main-stable while those mutable tags referenced the compromised version should also be treated as exposed.
A mutable tag can point to different images over time. Its current destination therefore cannot establish what an earlier deployment actually ran. Operators should inspect retained image digests, deployment records, registry logs, build logs, and package inventories to reconstruct exposure.
The public security issue also reports that affected Docker artifacts were built from the lookalike repository Berri-AI/litellm, rather than the normal BerriAI/litellm repository. That is a reported provenance discrepancy, not an established explanation of how the attacker gained access.
Because remediation status changed during the incident, current registry contents and maintainer guidance still need checking. A removed tag is a distribution action, not evidence that previously pulled images, local caches, or running containers are clean.
Start that investigation without launching Python inside a suspect environment. The startup behavior makes routine inspection commands potentially unsafe there.
Python Startup Triggered the Payload Without a LiteLLM Import
The malicious wheels contained three additional files: cook.pth, cook.py, and sitecustomize.py.
The first hook was particularly simple. cook.pth contained import cook. During normal initialization, Pythonâs site machinery processes .pth files and executes lines beginning with import. That caused cook.py to run without an application explicitly importing LiteLLM.
JFrog decoded the compressed, Base64-encoded program inside cook.py and identified a credential collector calling itself privcollect. Its targets extended well beyond the API key used by an individual AI application:
- AI development credentials and configuration, including files associated with Claude, Codex, Gemini, Cursor, and other tools.
- AWS, Azure, and Google Cloud credentials, plus cloud instance and task metadata.
- SSH and GPG material, TLS private keys, Kubernetes configuration, and service-account tokens.
- Browser login databases, cookies, history, shell histories, and package-manager credentials.
- CI/CD and infrastructure secrets associated with systems including Jenkins, GitLab Runner, Vault, and Terraform.
These are collection capabilities identified in the payload, not proof that every targeted secret was successfully recovered on every host.
The LiteLLM-specific database module is especially consequential for gateway operators. JFrog says it attempted to use DATABASE_URL to access LiteLLM_CredentialsTable and LiteLLM_ProxyModelTable. A compromised proxy could therefore expose stored upstream-provider credentials, rather than only secrets present in the current process.
On Linux, the collector also attempted to read environment variables from other accessible processes. Investigators should consequently assess what the compromised process could read, not just which variables a single application intentionally passed to LiteLLM.
A Dormant Loader Did Not Make the Package Safe
The second startup mechanism used sitecustomize.py, a module Python automatically attempts to import during normal initialization. JFrog says the injected module started a detached loader providing an hourly remote-code execution channel.
There is an important platform distinction: the loaderâs daemon path relied on os.fork and could not complete on Windows. That did not make Windows installations safe. The separate cook.pth mechanism could still invoke the credential stealer.
JFrog also reported a time-sensitive observation: when researchers retrieved the loaderâs dead-drop file, domain.txt, it returned an empty body. The loader was therefore dormant at that observation point, but changing the file could reactivate its remote-code delivery path.
The credential stealer operated independently of that file. An empty loader response was not a kill switch for the package.
Nor does the absence of a local success marker establish that no compromise occurred. According to JFrog, the collector created its run-once marker only after successful exfiltration. Defenders should not use that markerâs absence as a clean bill of health.
These distinctions matter when interpreting an apparently quiet host. No observed download, no visible application failure, or a disabled loader does not eliminate the separate credential-theft risk.
Why Reviewing the Git Tag Would Have Missed the Malware
JFrogâs artifact analysis found the three payload files under the wheelâs litellm-1.107.0.data/purelib/ directory. Wheel installers place files from that location into the environmentâs site-packages root, where the startup mechanisms could take effect.

The published source distribution did not contain those files. Its pyproject.toml did, however, include an added data = "cook" setting absent from the corresponding Git tag. That setting directed the Maturin build system to copy a build-time cook/ directory into the wheel.
The distinction is between reviewing source and verifying what users actually installed. A Git checkout could show legitimate library code while a separately produced wheel delivered additional executable files.
JFrog found that the malicious entries shared ZIP timestamps and metadata with legitimate wheel files. Researchers said this favored inclusion during ordinary wheel construction rather than later manual repacking. It did not establish which machine, CI system, account, or credential was compromised.
The supported conclusion is therefore narrower than âthe repository was hackedâ: the distributed artifacts were malicious, and the available evidence points toward build-artifact injection without resolving the initial access path.
For consumers, a clean source archive cannot vouch for every wheel published under the same version number. Inspection must cover the exact installed artifact, including its file manifest, added top-level modules, and startup hooks.
Marchâs Docker Assurance Does Not Apply to October
LiteLLMâs March security update identified PyPI versions and as compromised. The maintainers said that incident was believed to originate through a Trivy dependency used in a CI/CD security-scanning workflow.
Sources
- JFrog Security Researchresearch.jfrog.com
- public security issuegithub.com
- March security updatedocs.litellm.ai




