LiteLLM 1.107.0 Compromise Delivered Credential Stealer and Remote-Code Loader

Summary
StepSecurity found credential-stealing and remote-code-loader payloads in LiteLLM 1.107.0 PyPI wheels and Docker images. The stealer targeted developer, cloud and AI credentials; BerriAI removed affected artifacts and advised treating hosts as compromised.
Key points
- All seven PyPI 1.107.0 wheels contained cook.pth, cook.py and sitecustomize.py; the same payload files were present in affected Docker images. Python startup hooks ran them automatically.
- The privcollect stealer targeted browser data, SSH and GPG keys, cloud and CI secrets, AI coding-tool credentials, process environments and LiteLLM proxy credentials. It encrypted collected data and attempted to send it to hxxp://www.litellm[.]dev/healthcheck.
- A separate daemon polled an attacker-controlled GitHub dead drop hourly and executed code from a supplied host. The dead-drop file was empty at release time; the article says the loader fails silently on Windows.
- Build provenance linked v1.107.0 to the lookalike Berri-AI/litellm repository, where ten commits added the payload and changed the build configuration. BerriAI said stolen developer GitHub OAuth tokens were used to alter its release workflow; the initial access method remains unconfirmed.
- The malicious artifacts were built and published through the modified release workflow. The article explains that this allowed them to carry legitimate pipeline signatures and provenance.
- BerriAI removed the PyPI release and affected container images. StepSecurity advises treating hosts that installed the wheel or ran an affected image as compromised, rebuilding them and rotating credentials they could access.
Article Details
- Attack Vectors
- A lookalike Berri-AI/litellm repository was used as the source for the official v1.107.0 release workflow, adding startup-hook payloads to the published wheels and Docker images.
- According to BerriAI, stolen developer GitHub OAuth tokens were exposed in application logs; an organization owner's token was used to override branch protection and alter the release workflow.
- The installed cook.pth and sitecustomize.py files ran payloads automatically when Python started, without requiring an import of LiteLLM.
- The privcollect stealer collected browser credentials, keys, cloud and CI secrets, process environments, AI coding-tool credentials, and LiteLLM proxy database credentials, then encrypted and sent the bundle to an attacker-controlled endpoint.
- A detached daemon polled an attacker-controlled GitHub dead drop hourly and, if given a hostname, downloaded and executed Python code from its /codepy path.
- Defensive Notes
- Treat hosts that installed a v1.107.0 wheel or ran an affected image as compromised; rebuild them rather than relying on in-place repair.
- From a shell, terminate any process holding /tmp/remote_code_loader.lock, remove cook.pth, cook.py, and malicious sitecustomize.py files from affected site-packages directories, and remove associated bytecode.
- Rotate all credentials the host could reach, including browser passwords and cookies, SSH and GPG keys, cloud and instance-role credentials, CI and Vault secrets, AI tool tokens, and LiteLLM provider API keys, master key, and salt key.
- Pin a clean LiteLLM version or image by digest; the article recommends litellm==1.106.2 or the v1.106.2 image by digest.
- Search network logs for litellm.dev, the dead-drop URL, and requests ending in /codepy. The article identifies a /codepy request as evidence that attacker-supplied code ran.
- Audit release-workflow protections, approval gates, and application logs for exposed long-lived developer tokens. BerriAI had not confirmed initial access and said it suspected a recently patched vulnerability.
Indicators of compromise
| Type | Indicator | Context |
|---|---|---|
| DOMAIN | litellm[.]dev | Lookalike attacker-controlled domain used for credential-stealer exfiltration. |
| DOMAIN | www[.]litellm[.]dev | Attacker-controlled exfiltration host used by privcollect. |
| SHA256 | 03ac2a8b752605d1d7710979c17ff18b03dd978203ba23ba97fd8ce3d6f897ea | Windows SHA-256 of the privcollect cook.py payload. |
| SHA256 | 0aaf7ba346d41ef2f40390436738b001180d5a1c03aa093f121078a9969d9a1a | SHA-256 of the compromised macOS arm64 LiteLLM 1.107.0 wheel. |
| SHA256 | 12d4ccc5c6f8d35cf4f2cf233b7f3e418e863e657d81ff5f5fc9e210005b9484 | SHA-256 of the compromised Windows amd64 LiteLLM 1.107.0 wheel. |
| SHA256 | 1bbce8caa94f01c0aaa0b7ddae51553a8a32e1ce53d96d44fe583272aff7ad00 | SHA-256 of the compromised musllinux x86_64 LiteLLM 1.107.0 wheel. |
| SHA256 | 34bef04fe88ac9d0aae0475630b1738681d15b94f233ac8aa46eacf5968305fa | SHA-256 of the malicious sitecustomize.py remote-code loader. |
| SHA256 | 462d0c9f67ca522d9e0e4acd245e90b36ce0d5353604a66bb7c43a1ec4a6fcf7 | SHA-256 of the compromised manylinux x86_64 LiteLLM 1.107.0 wheel. |
| SHA256 | 668169d35b87bf51324080390b1b1c5ab12bd335cfe5f1a99e3689abd5e02ae6 | SHA-256 of the compromised manylinux aarch64 LiteLLM 1.107.0 wheel. |
| SHA256 | 7598727f209d717041db37f7dca271d3a7d328a279890e0e1d55375729aeb86d | SHA-256 of the compromised macOS x86_64 LiteLLM 1.107.0 wheel. |
| SHA256 | 7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb | SHA-256 of the malicious cook.pth startup hook in the compromised release. |
| SHA256 | 84dc8c82c0a4a4a62552ef826b49fcc86d1a5c4a5d0f2c06665723f93d129d7d | Windows SHA-256 of the malicious cook.pth startup hook. |
| SHA256 | 9dd0a3926f96a37eb86cf1ee2310d9be93139cc4ebef3ef9e2efe9531390be25 | SHA-256 of the privcollect cook.py credential-stealer payload. |
| SHA256 | b6122440d0d9cb1eb1ade9933f49214da8c31288de7710c076c2680dfa528465 | Windows SHA-256 of the malicious sitecustomize.py payload. |
| SHA256 | c2e32d0ce2548aa662c18bf5001911a79fe5b30cf8357132275add02fdcde054 | SHA-256 of the compromised musllinux aarch64 LiteLLM 1.107.0 wheel. |
| URL | hxxp[:]//www[.]litellm[.]dev/healthcheck | Exfiltration endpoint receiving the encrypted credential bundle. |
| URL | hxxps[:]//github[.]com/Berri-AI/litellm | Lookalike source repository identified as the source used to build the compromised release. |
| URL | hxxps[:]//raw[.]githubusercontent[.]com/letters9813/pythonclient-test/main/domain.txt | Attacker-controlled dead-drop resource polled hourly by the remote-code loader. |
MITRE ATT&CK
T1005 · Data from Local SystemThe payload collected files, histories, process environments, and LiteLLM proxy database contents from infected hosts.T1027 · Obfuscated Files or InformationThe cook.py payload concealed its Python code in a base64-encoded, zlib-compressed blob.T1041 · Exfiltration Over C2 ChannelThe credential stealer sent its encrypted collection to the attacker-designated exfiltration endpoint.T1059.006 · PythonThe loader executed Python code downloaded from the host named in the attacker's dead-drop file.T1071.001 · Web ProtocolsThe loader fetched its dead-drop file over HTTPS and retrieved second-stage code over HTTP.T1078.004 · Cloud AccountsA stolen organization owner's account token was used to override branch protection and change the release workflow.T1102.001 · Dead Drop ResolverThe daemon polled a file in an attacker-controlled GitHub repository for the hostname of its next-stage server.T1105 · Ingress Tool TransferThe daemon fetched Python code from the supplied host's /codepy path.T1119 · Automated CollectionThe payload ran 16 collection modules covering browser data, keys, cloud and CI secrets, AI tool credentials, and other host data.T1195.002 · Compromise Software Supply ChainThe release was built from a lookalike repository containing attacker-added payload files and build-configuration changes.T1546.018 · Python Startup Hookscook.pth and sitecustomize.py executed automatically on Python startup in affected environments.T1550.001 · Application Access TokenStolen GitHub CLI OAuth tokens were used to alter the release workflow, satisfy approval, and delete workflow-run records.T1552.001 · Credentials In FilesThe stealer collected credentials and keys from files including cloud credential files, SSH and GPG keys, and developer configuration files.T1555.003 · Credentials from Web BrowsersThe stealer collected browser login data and decrypted passwords from supported browser databases.T1560 · Archive Collected DataCollected data was packaged into a tar.gz bundle before exfiltration.
