Compromised LiteLLM 1.107.0 on PyPI Installs a Credential Stealer and Backdoor
⚠️ Security Alert: Credential Stealer and Backdoor Found in LiteLLM 1.107.0
A critical security compromise has been identified in the LiteLLM version 1.107.0 release hosted on PyPI. This version contains a sophisticated credential stealer and a remote code execution (RCE) backdoor.
🚨 Executive Summary
The malicious release affects all seven distributed wheels across Linux, macOS, and Windows. The attack is particularly dangerous because the implant triggers upon the start of any Python process on the infected host—regardless of whether litellm is actually imported.
Note: The companion packages pinned by this version,
litellm-proxy-extras==0.4.110andlitellm-enterprise==0.1.78, have been verified as clean.
🛠️ Anatomy of the Attack
What the Malware Does
Once litellm==1.107.0 is installed, it deposits three specific files into the site-packages directory. The malware performs the following actions:
- Data Exfiltration: It targets a wide array of sensitive information:
- SSH Keys
- Cloud Provider Credentials
- CI/CD Secrets
- AI Tool Tokens
- Browser-stored Passwords
- LLM Provider Keys (extracted from the LiteLLM proxy database)
- Persistence & Command and Control (C2): A daemon runs every hour to:
- Read a server address from a specific GitHub file.
- Re-execute the credential stealer.
- Download and execute arbitrary code from the identified server.
Infection Flow
🔍 Forensic Analysis: How it Happened
The Injection Point
The attacker modified the pyproject.toml file within the source distribution (sdist). A single line was added to the maturin build section:
[tool.maturin]
python-source = "."
data = "cook" # <--- MALICIOUS INJECTION
python-packages = [ "litellm_cli" ] # Legitimate
The data = "cook" directive instructs the build system to include the cook/ folder in the resulting wheel. Interestingly, the cook/ folder was omitted from the sdist itself, making the injection nearly invisible unless the pyproject.toml was scrutinized.
Discrepancies in the Release
SafeDep discovered that the PyPI release does not match the official Git tag v1.107.0 (commit 66c8f5b). Instead, the sdist was based on a later commit (a8113b0) with several manual edits:
| File | Change Description |
|---|---|
Cargo.toml (x4) | Added readme = README.md |
pyproject.toml | Version downgraded |
pyproject.toml | Pinned dependencies to rc2 values |
pyproject.toml | Added data = "cook" |
By increasing decreasing the version number and aligning pins with the rc2 release, the attacker ensured that a dependency diff against the release candidate would appear normal.
The Build Pipeline
Evidence suggests the wheels were built using the official BerriAI pipeline:
- Tooling: Used
maturin 1.9.4(matching legitimate releases). - Timestamps: Native builds occurred at 11:20 (macOS), 11:21 (Linux), and 11:37 (Windows) UTC.
- Formatting: Windows wheels used CRLF line endings across all 2,804
.pyfiles, consistent with a Windows git checkout.
Conclusion on Vector:
SafeDep concludes with moderate-to-high confidence that the private release pipeline was compromised. This likely involved stolen maintainer/bot credentials or a compromised private branch, rather than a simple PyPI token theft.
📦 Payload Technical Details
Payload 1: cook.py
The execution is triggered via a .pth file. In Python, any line starting with import in a .pth file is executed upon interpreter startup.
The Chain: cook.pth import cook cook.py.
The cook.py file contains a heavily obfuscated payload. The decompression logic can be represented as:
Decoded Configuration Snippet:
PC_URL = 'http://www.litellm.dev/healthcheck'
PC_TOKEN = 'XWiA8gZNa7NcX2XRoAEb' # Sent as X-Token header
PC_PUBKEY = '-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMII...'
File Manifest (from RECORD)
The following files were added to the wheel:
litellm-1.107.0.data/purelib/cook.pth(12 bytes) The Triggerlitellm-1.107.0.data/purelib/cook.py(22,252 bytes) The Stealerlitellm-1.107.0.data/purelib/sitecustomize.py(25,509 bytes) The Loader/Backdoor
