Two hours on PyPI, longer on the machine
The short version of this story that will circulate is the window: uploaded at 11:39 UTC, gone from PyPI by 13:23 UTC, with Datadog reporting a PyPI quarantine at 13:20 UTC. Under two hours. That framing understates what the malware was built to do.
Installing the wheel placed three files in the affected environment's site-packages: cook.pth, cook.py and sitecustomize.py. During normal Python site initialisation, Python processes the .pth file — cook.pth imports cook.py — and imports sitecustomize, so the stealer and the backdoor's daemon start without any application importing LiteLLM. Other programs using the same environment can run the code too: pip, an IDE's language server, a CI job. The scope is the affected environment, not the whole host — a separate, isolated Python installation on the same machine is not automatically infected, and startup flags or isolated configurations can change whether site initialisation runs at all. But within the affected environment the trigger is ordinary use, and because the three files sit loose in site-packages rather than inside the package directory, removing the litellm package leaves them behind. An environment can report itself clean, on a safe version, while the stealer still runs at the next normal Python start. Datadog's guidance is explicit on the point: the dropped files must be removed manually, and running the environment's own Python or pip before cleanup triggers the payload again — which is why the remediation below starts with not running them.
What it took was comprehensive. Alongside the usual targets — SSH and GPG keys, cloud credentials including instance-metadata credentials, browser passwords, shell history — the stealer had a module for AI development tools, covering sessions and tokens for Claude Code, Cursor, Copilot, Codex, Gemini CLI and a list of similar tools, and a module, db_litellm, that reads a configured database connection and dumps the tables where a LiteLLM proxy stores upstream provider credentials. That second target is the structural one, with a condition attached: it fires where a proxy database is configured, which is the common production deployment, not every installation. LiteLLM is widely deployed as the one gateway through which a whole organisation calls OpenAI, Anthropic, Google and the rest. Where that deployment pattern holds, a compromised proxy host is not one developer's key. It is the key cabinet.
The pipeline published it
The release was not a typosquat or a fake package page. LiteLLM's incident account, quoted by The Hacker News from its director of security, Oliver Jensen, says the actions were taken through three engineers' GitHub accounts, apparently using stolen GitHub CLI OAuth tokens. One account triggered the private project-releaser workflow, pointed at a fork named Berri-AI/litellm, a hyphen away from the real organisation; SafeDep's account adds that an organisation owner's token was used to bypass branch protection and point the workflow at the fork. Another account approved the run. The official pipeline then built the wheels and images and published them through the normal channels, with build provenance that recorded the malicious fork as the source.
Jensen also said what LiteLLM does not know: the mechanism by which the tokens were acquired has not been identified, and the company cannot yet assert that the accounts have no further compromise. SafeDep reports a LiteLLM belief that the tokens were taken from logs of an internal deployment exposed to the internet. Treat that as a working theory from the affected company, not a confirmed root cause. The confirmed mitigations are narrower: the involved tokens are revoked, trusted publishing links to the GitHub organisation have been removed from the registries, and the organisation has been cut down to one unaffected user for now. The Hacker News also reports that PyPI quarantined the malicious package; what PyPI's internal process involved beyond that, the reporting does not say.
The backdoor half of the payload deserves the same care. Researchers confirmed credential-stealing code, an exfiltration endpoint and a persistent remote-code loader in the malicious release. The loader's hourly daemon read its server address from a GitHub file; Datadog reports that file only ever held test values and that it observed no second-stage payload. But the GitHub account behind the file was deleted about two hours after the release — SafeDep found it returning 404 by 13:40 UTC — and SafeDep could not recover an earlier server address, so execution during the brief interval before the repository disappeared cannot be excluded: SafeDep notes that hosts which ran the daemon before the deletion could have received and run second-stage code. The available evidence does not establish how many hosts successfully transmitted credentials or executed additional attacker-supplied code.
What to do if 1.107.0 touched an environment
The check is fast. Look in site-packages for cook.pth, cook.py or a sitecustomize.py that nobody on the team wrote, or for the marker files /tmp/.pc_once_72129118c59f5636c0bb and /tmp/remote_code_loader.lock on Linux and macOS hosts. Two cautions belong with the check. First, sitecustomize.py is a legitimate Python mechanism and some environments ship their own; identify the malicious file by its location, content and the known indicators before deleting anything by filename alone. Second, the marker files are indicators, not a test: the first is written after the stealer uploads its bundle, the second is the daemon's lockfile, and either can be absent — after a reboot, in a different environment, or before a payload stage completes. Their absence is not proof of safety. Anyone who ran pip install -U litellm, or a requirements file without an upper bound, late on the morning of 21 October UTC is in the group that needs to look, as is anyone whose Docker build pulled litellm/litellm:latest, main-latest or main-stable that day — the floating tags are why a team can be affected without ever having chosen version 1.107.0. For Docker, check image digests and deployment records, not just current tag names: a tag repointed to a clean image does not change an image already pulled or a container already running.
If the files are present, treat the environment as compromised, not merely dirty. Isolate it and preserve relevant forensic evidence before cleanup, and do not run its Python interpreter or pip while the startup hooks remain active. From a trusted environment, identify and remove cook.pth, cook.py and the malicious sitecustomize.py from every affected site-packages location — or, preferably, rebuild the environment from a known-clean image. Remove the compromised package or image and restore a verified clean version, 1.106.2, using pinned hashes or image digests. From a separate clean machine, revoke and rotate potentially exposed credentials: cloud keys, provider API keys, AI-tool sessions, SSH and GPG keys, developer tokens. Then review network, identity-provider, cloud, CI/CD and application logs for suspicious activity after the first possible exposure. And if second-stage execution cannot be ruled out on a host, treat it as potentially fully compromised and follow an incident-response process rather than relying on file deletion alone. Manual removal of the three files is necessary; it is not, by itself, proof of complete remediation.
This is LiteLLM's second compromised PyPI release incident in 2026. Both involved malicious Python startup behaviour, but investigators have not established a common attacker or initial access path: the March incident, affecting versions 1.82.7 and 1.82.8, was linked by Datadog to TeamPCP activity, while the October account describes compromised developer credentials redirecting an official publishing workflow toward a lookalike repository. The recurrence makes dependency pinning, artifact verification and release-workflow security worth renewed scrutiny — and the October incident specifically raises questions about how three engineers' stolen CLI tokens could be enough to turn a project's own pipeline into the delivery mechanism.
Sources
- [1] SafeDep, "Compromised LiteLLM 1.107.0 on PyPI Installs a Credential Stealer and Backdoor", 21 October 2026 — read directly for this article: full technical analysis (three planted files and their behaviour, stealer target list including the db_litellm database module, exfiltration to the lookalike domain www.litellm[.]dev, timeline 11:39–14:20 UTC with Docker Hub tags removed or repointed at 14:20 UTC, the dead-drop account returning 404 by 13:40 UTC and the server address unrecovered, wheel hashes, clean versions, and LiteLLM’s account of the token theft and lookalike fork, including the belief that the tokens came from logs of an exposed internal deployment)Read source
- [2] Datadog Security Labs, "LiteLLM supply chain compromise: What you need to know", 21 October 2026 — read directly for this article: about 23 million weekly downloads (its estimate); PyPI quarantine at 13:20 UTC and affected Docker images removed at 13:53 UTC on its timeline (SafeDep’s timeline differs on the Docker endpoint, giving 14:20 UTC; the reason is not established); stolen GitHub CLI OAuth tokens from three engineers; the dead-drop file held test values only and no second-stage payload was observed; remediation steps including manual file removal and rotation from a clean machine; the March 2026 incident (versions 1.82.7 and 1.82.8) linked to TeamPCP, with no connection established to this oneRead source
- [3] The Hacker News, "LiteLLM Compromised in Supply Chain Attack Delivering Credential Stealer and Backdoor", 21 October 2026 — read directly for this article: PyPI quarantined the malicious package; LiteLLM security director Oliver Jensen on the record (actions taken through three engineers’ GitHub accounts using stolen GitHub CLI OAuth tokens, one account triggering the release run and another approving it, tokens revoked, the mechanism by which the tokens were acquired not yet identified, the organisation reduced to one unaffected user, registry trusted links removed); reports from SafeDep, Socket, StepSecurity and UpwindRead source
- [4] OpenSourceMalware, "LiteLLM 1.107.0 PyPI Wheel Contains a Credential Stealer and Persistent Python Backdoor", 21 October 2026 (independent wheel analysis: payload absent from the v1.107.0 git tag, hashes matching Upwind’s report, hourly C2 polling and persistence mechanics)Read source