#Alert
So it's not only PHP that was vulnerable today (patch yours NOW!) but also, one of the prominent and widely used LLM Gateway - LiteLLM AI Gateway was (again) backdoored.
Not sure who discovered the backdoor, but it's serious.
Here's the information:
Version: LiteLLM 1.107.0 (PyPI and the official Docker images).
One line was added to the build config: `data = "cook"` under [tool.maturin].
That directive makes maturin bundle a directory named cook/ into the wheel's data section, and pip installs it as top-level site files.
Three files land next to site-packages, not inside the litellm package: a 12 byte cook.pth containing `import cook`, a one-line cook.py that unpacks a 61,000 byte credential stealer, and a sitecustomize.py that runs an hourly remote code loader.
Because Python processes .pth files and imports sitecustomize during interpreter startup, the payload runs on any Python start. An environment that never imports litellm is still affected, and using pip from that environment to investigate re-triggers it.
The collector is broad. It takes browser password stores, SSH, GPG and TLS private keys, AWS, Azure, GCP and Kubernetes credentials, instance and ECS metadata roles, CI tokens, .env files, and the auth files for Claude, Codex, Gemini, Cursor and Copilot.
It also queries your proxy's own database, pulling every saved provider credential and model configuration out of LiteLLM_CredentialsTable and LiteLLM_ProxyModelTable.
Everything is encrypted with an embedded RSA-4096 key and POSTed to www.litellm.dev/healthcheck, a domain the attacker controls.
The second component is the part that should worry platform teams. sitecustomize.py polls a domain list from a GitHub repository every hour and executes whatever Python it downloads from that domain, with no signature or checksum. The attacker never needs to ship a new package version to change what runs on your hosts.What makes this hard to audit: the malicious commits were never merged to main, and the official v1.107.0 tag points at a clean, signed commit.
The published artifacts came from a repository recorded as Berri-AI, one hyphen from BerriAI. Reviewing the tag, or the main branch, would have told you nothing was wrong.
Current state as of this afternoon: PyPI has quarantined 1.107.0 and rolled latest back to 1.106.2, the compromised image tags are gone from GHCR and Docker Hub, the attacker's GitHub account and C2 pointer repository have both been taken down, and the exfil server is still listening.
If you deployed 1.107.0, check for /tmp/.pc_once_72129118c59f5636c0bb and /tmp/remote_code_loader.lock. If either exists, rebuild rather than patch, and rotate every credential the process could read, including the keys stored in your proxy database.
Two controls would have blocked most of this: lockfiles with hashes, and OIDC trusted publishing so a long-lived publish token never reaches a compromised CI machine. The longer term fix is pinning source revisions rather than version tags, since in this incident the tag was never the source of the bad build.
#SupplyChainSecurity #AppSec #Python #LLMOps #LiteLLM