LiteLLM 1.107.0 trojanized on PyPI and Docker via stolen GitHub CLI tokens: infostealer and RCE backdoor through Python startup hooks
Matéria consolidada. Reúne 10 matérias que o Tifon tinha publicado separadamente sobre a mesma história. A IA reescreveu o relatório com o que as 7 fontes trouxeram em 23/10/2026 00:07; os links antigos trazem para cá.
Fontes: bleepingcomputer.com ↗ thehackernews.com ×2 ↗ gbhackers.com ↗ theregister.com ↗ wiz.io ↗ aikido.dev ↗ safedep.io ↗
The LiteLLM release 1.107.0 (a widely used open source LLM proxy and AI gateway developed by BerriAI, about 23 million weekly downloads per theregister.com and gbhackers.com, or about 92 million monthly PyPI downloads per bleepingcomputer.com) was trojanized on PyPI on 21 October 2026 and carries a credential stealer (privcollect) plus a remote code execution backdoor, effectively a RAT (thehackernews.com). All seven wheels (Linux, macOS, Windows) drop three extra files in site-packages, two of which run whenever any Python process starts, even one that never imports litellm (safedep.io, bleepingcomputer.com). The Docker images (GHCR and Docker Hub, tags v1.107.0, latest, main-latest, main-stable) were also trojanized (wiz.io, aikido.dev, theregister.com). The exposure windows (UTC) were 11:39 to 13:23 for pip installs of unpinned versions and 11:46 to 14:20 for the Docker tags (thehackernews.com, bleepingcomputer.com). Security vendors detected the release within about six to seven minutes of publication (bleepingcomputer.com, gbhackers.com). LiteLLM says the release was pushed through three engineers' GitHub accounts using stolen GitHub CLI OAuth tokens; it suspects the tokens leaked from the logs of an internal, publicly exposed LiteLLM deployment, where Claude Code responses had embedded them, and how the attacker got into that deployment is unknown (thehackernews.com). The malicious code is not in the upstream BerriAI GitHub source: the release workflow was pointed at the lookalike organization Berri-AI (wiz.io, thehackernews.com, gbhackers.com), while SafeDep says the cause can only be confirmed from BerriAI's pipeline logs (safedep.io). Wiz observed stolen AWS credentials being validated about 4.5 hours after exfiltration, consistent with LLMjacking (thehackernews.com). The same .pth execution behavior was seen in the earlier TeamPCP-linked LiteLLM compromise in March (thehackernews.com), which reportedly exposed more than 2,500 organizations and 434,000 CI/CD pipelines (CloudSEK, via theregister.com), but Socket found no evidence linking the two incidents (thehackernews.com). The maintainer says customers on the private enterprise offering were not impacted (bleepingcomputer.com). Anyone who installed or pulled this version should treat all reachable credentials as compromised. The last known safe version is v1.106.2 (wiz.io, theregister.com, bleepingcomputer.com). BerriAI did not respond to The Register (theregister.com).
Detalhes técnicos
- Timing: the malicious version was uploaded at 11:39 UTC (theregister.com; PyPI exposure 11:39:51 to 13:23 per bleepingcomputer.com). Socket flagged seven malicious wheels about seven minutes after publication (gbhackers.com). Aikido published its analysis at about 13:05 UTC, when PyPI had quarantined the version but the Docker image was still live on Docker Hub (aikido.dev). GHCR tags were removed by 13:51 UTC (bleepingcomputer.com), Wiz puts the Docker tag removal at about 13:53 UTC (wiz.io), and Docker Hub exposure ran until 14:20 UTC (thehackernews.com, bleepingcomputer.com). The GitHub account letters9813 and its repository were taken down at about 13:30 UTC per Wiz (thehackernews.com) or started returning 404 at about 13:40 UTC per SafeDep, so the backdoor no longer finds a server address (safedep.io).
- Intrusion chain (LiteLLM, via thehackernews.com):
- On October 19, LiteLLM temporarily expanded release permissions for two engineers.
- The attacker held three sets of developer GitHub CLI credentials, one able to run workflows.
- A token of a GitHub organization owner was used to disable branch protections and force-push changes.
- The workflow was pointed at the lookalike repository Berri-AI/litellm instead of BerriAI/litellm, so the poisoned artifacts were signed and published.
- Attackers used one user's account to trigger the project-releaser run and another's to approve it.
- How the internal deployment became public and how the attacker got in is unknown; LiteLLM theorizes a recently patched vulnerability.
- Provenance evidence (Socket, via gbhackers.com): container build provenance listed Berri-AI/litellm as the source instead of BerriAI/litellm. The private BerriAI/project-releaser workflow showed a source-owner override selecting the hyphenated organization. The evidence does not show how the override was authorized, whether an account or token was compromised, or whether that workflow published the wheels.
- Commits in the lookalike org: on 2026-10-21 between 08:56 and 10:46 UTC the attacker pushed 10 commits to github.com/Berri-AI/litellm using the email [email protected]. The first nine are GitHub-signed and add the persistence files, bump the version and add
data = "cook"to pyproject.toml. A final unsigned commit under [email protected] addsCOPY cook ./cookto the Dockerfiles (wiz.io). - Affected artifacts:
litellm-1.107.0wheels for macOS (x86_64, arm64), manylinux_2_28 (x86_64, aarch64), musllinux_1_2 (x86_64, aarch64) and Windows (win_amd64), plus the sdistlitellm-1.107.0.tar.gz, which has no payload files but a tamperedpyproject.toml(thehackernews.com). Container tags v1.107.0, latest, main-latest and main-stable all resolved to the same image index, which widened exposure beyond pinned deployments (gbhackers.com). - Injection: the attacker did not modify LiteLLM application code; only the installation package was altered (bleepingcomputer.com). The sdist
pyproject.tomlhas one extra line in the maturin section,data = "cook". It copies acook/folder, absent from the sdist and from the source repo, intolitellm-1.107.0.data/purelib/, and pip installs it into site-packages (safedep.io, aikido.dev). The build changes also copy the malicious directory into Docker build stages (gbhackers.com). No public commit in BerriAI/litellm contains it (safedep.io). - Tag mismatch: tag v1.107.0 (commit 66c8f5b) declares version 1.108.0. The sdist matches a later main commit (a8113b0) plus edited files. The version was reset to 1.107.0 and the companion pins were set to the rc2 values, so a dependency diff against rc2 shows nothing unusual (safedep.io).
- Build provenance: the wheels were built with maturin 1.9.4, like the legitimate releases, with separate native builds on macOS, Linux and Windows. SafeDep checked 539 public GitHub Actions runs and found none that built the release, and PyPI has no provenance attestations for these versions. SafeDep assesses with moderate to high confidence that BerriAI's private release pipeline built the wheels from attacker-modified git source (safedep.io).
- Files dropped:
cook.pth(12 bytes,import cook, runs at every interpreter start),cook.py(the infostealer, a single obfuscated line that decompresses and executes a 61,000-byte payload) andsitecustomize.py(the RAT/backdoor) (aikido.dev). Because the .pth hook fires in every Python process, it covers applications, pip, IDE language servers and CI jobs, and re-triggers when Python or pip is launched during investigation (safedep.io, gbhackers.com, bleepingcomputer.com). Execution happens before LiteLLM is imported (thehackernews.com). Wiz describes the combined .pth and sitecustomize.py technique as the first documented in the wild (thehackernews.com). - Stealer (internally named privcollect, 16 modules):
- It collects SSH keys, shell history, GPG and TLS keys, .env files and all environment variables, including
/proc/<pid>/environon Linux (aikido.dev, safedep.io, bleepingcomputer.com). - It collects browser credentials, cookies, autofill data and history for Chrome, Firefox, Edge and Safari (wiz.io, aikido.dev, theregister.com, bleepingcomputer.com).
- It collects AWS, Azure and GCP credentials, including
~/.aws/, EC2/ECS IMDS and cloud metadata, GCP service account keys and application default credentials, Azure CLI tokens, plus Docker and Kubernetes secrets (aikido.dev, wiz.io, theregister.com). - It collects CI/CD secrets (GitLab runner, Jenkins, Vault), Git/GitHub/npm/PyPI credentials and AI developer tool configs (Claude Code, Cursor, Copilot, Windsurf, Gemini CLI, Codex and others), including AI tooling credential JSON files (aikido.dev, thehackernews.com, gbhackers.com).
- It collects API keys for OpenAI, Anthropic, Cohere and other LLM providers (wiz.io, theregister.com).
- On LiteLLM Proxy hosts it dumps LiteLLM_CredentialsTable (via
SELECT * FROM "LiteLLM_CredentialsTable" LIMIT 500) and LiteLLM_ProxyModelTable (wiz.io, aikido.dev). Socket saw no evidence of successful theft from individual deployments through this module (gbhackers.com).
- It collects SSH keys, shell history, GPG and TLS keys, .env files and all environment variables, including
- Exfiltration: data is encrypted with AES-256-CBC, the key is wrapped with a hardcoded RSA-4096 public key (RSA-4096-OAEP per gbhackers.com), and the tar.gz is POSTed to
www.litellm[.]dev/healthcheck, a deceptive endpoint, with a hardcodedX-Tokenheader (XWiA8gZNa7NcX2XRoAEb) and the User-AgentMozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0)(safedep.io, aikido.dev, wiz.io, theregister.com, thehackernews.com). The marker file/tmp/.pc_once_72129118c59f5636c0bblimits collection to once per host (aikido.dev, wiz.io). - Backdoor (
sitecustomize.py): it takes the lock/tmp/remote_code_loader.lock, then forks and detaches a daemon. Every hour it reads a domain fromdomain.txtin the attacker's GitHub repository (letters9813/pythonclient-test, via raw.githubusercontent.com). It re-runs an embedded stealer copy with no once-per-host marker, then downloads (HTTP GET) andexec()s Python fromhttp://<domain>/codepy(https://{domain}/codepyper thehackernews.com) with no sandboxing or signature/hash verification (safedep.io, aikido.dev, thehackernews.com, gbhackers.com). The hourly retry does not confirm hourly exfiltration (gbhackers.com). Wiz says it runs on Linux and macOS only, and that the marker write fails on Windows (wiz.io, thehackernews.com). - Second stage: Wiz says
domain.txtwas never populated at the time of analysis and held only test values (wiz.io, thehackernews.com); the pointer was empty in one Socket observation, which blocked that stage but not the collector (gbhackers.com). SafeDep says hosts whose daemon ran earlier could have received second-stage code, and it could not recover the server address (safedep.io). - Post-exfiltration abuse (Wiz, via thehackernews.com): AWS instance role credentials from CI runners and Kubernetes nodes were checked with sts:GetCallerIdentity, then bedrock:ListFoundationModels and ListModels. In a few environments the attacker also enumerated IAM (ListRoles, ListUsers, ListAccessKeys) and ran general discovery. Stolen AWS credentials were validated about 4.5 hours after exfiltration, consistent with LLMjacking.
- Attribution: Socket notes the RSA public keys, exfiltration implementation and backdoor behavior differ from the March TeamPCP attack. No link is established, and the role of credentials stolen in March is unverified (thehackernews.com). The project was breached in March by TeamPCP via the compromised Trivy scanner in its CI/CD pipeline (bleepingcomputer.com).
- Clean artifacts: versions 1.106.2, 1.107.0rc1 and 1.107.0rc2, and the pinned companions litellm-proxy-extras==0.4.110 and litellm-enterprise==0.1.78 (safedep.io).
- Commit visibility: the malicious commits remain visible via the parent repo through fork object sharing (compare a8113b0d...20535d8f) (wiz.io).
- Detection and other analyses: Socket and Endor Labs, among other vendors, detected the release (bleepingcomputer.com). SafeDep, Socket, StepSecurity and Upwind also published reports on this compromise (thehackernews.com).
Remediação
- Identify every host or container that installed
litellm==1.107.0or pulled/ranlitellm/litellm:1.107.0, including thelatest,main-latestandmain-stabletags, inspect image digests, and pin to v1.106.2, by digest where possible (wiz.io, aikido.dev, thehackernews.com, gbhackers.com, bleepingcomputer.com). - Investigate every environment where Python ran after installation, including proxy containers and CI runners (theregister.com). Isolate those hosts, stop affected deployments, and inspect them without launching the Python interpreter, preserving evidence with trusted tooling (gbhackers.com, bleepingcomputer.com).
- Check for
/tmp/.pc_once_*(exfiltration already fired) and/tmp/remote_code_loader.lock(C2 daemon ran or is running) (aikido.dev). - Hunt for
cook.pth,cook.pyandsitecustomize.pyin site-packages, and for traffic to litellm[.]dev (wiz.io, aikido.dev). - Block the listed domains and the GitHub C2 lookup path (aikido.dev).
- Treat all secrets on affected systems as compromised and rotate them from a clean system: cloud credentials, LLM provider API keys, keys in the LiteLLM_CredentialsTable, database connection strings, CI/CD secrets, and SSH/GPG/TLS keys (aikido.dev, wiz.io, theregister.com, thehackernews.com, gbhackers.com, bleepingcomputer.com).
- Remove the affected version and image, and rebuild affected systems from reviewed artifacts or clean backups. Removing LiteLLM or deleting its package directory alone neither reverses the exposure nor stops an existing loader or leftover startup files (aikido.dev, gbhackers.com, bleepingcomputer.com; the thehackernews.com remediation text is truncated).
- Maintainers should validate repository identities, release permissions and published artifacts against approved sources (gbhackers.com).
- Follow the threat-hunting and mitigation guidance published by Aikido, Wiz and Socket (theregister.com).
- Vendor actions: LiteLLM revoked all involved tokens, removed all but one unaffected user from its GitHub organization, and removed trusted links to its GitHub organization from the public registries. It cannot yet rule out further access to the affected accounts (thehackernews.com).
Relatos divergentes
- Origin of the malicious code and initial access: Wiz attributes it to malicious commits in the lookalike organization Berri-AI that fed the release pipeline (wiz.io, repeated by theregister.com). SafeDep says no public commit in BerriAI/litellm contains it and that the exact cause (compromised maintainer or bot credential, private branch or mirror, or the build reference) can only be confirmed from BerriAI's pipeline logs (safedep.io). Socket's provenance findings show only the source-owner override to Berri-AI and say they do not show how it was authorized or whether that workflow published the wheels (gbhackers.com). The most recent account, from LiteLLM itself, says the release was pushed through three engineers' GitHub accounts using stolen GitHub CLI OAuth tokens, probably leaked from logs of a publicly exposed internal deployment, with the workflow pointed at the lookalike repository (thehackernews.com); this is the vendor statement and the most authoritative, although how the deployment was breached remains unknown. An earlier version of this record said the token theft vector was unknown.
- Docker image status and removal time: Aikido says the Docker image was still live on Docker Hub at the time of its report (aikido.dev), Wiz says the Docker tags were removed at about 13:53 UTC (wiz.io), and bleepingcomputer.com says GHCR tags were removed by 13:51 UTC while Docker Hub exposure lasted until 14:20 UTC (also thehackernews.com). The 14:20 UTC end for Docker Hub is the most recent and detailed account; later reports say the malicious images were removed (thehackernews.com, theregister.com).
- GitHub C2 repository takedown: SafeDep reports 404 responses at about 13:40 UTC (safedep.io), whereas thehackernews.com, citing Wiz, says GitHub took the file down at about 13:30 UTC.
- Detection speed: Socket flagged the wheels about seven minutes after publication (gbhackers.com), while bleepingcomputer.com says security vendors detected the attack within six minutes.
- Download volume: about 23 million weekly downloads (theregister.com, gbhackers.com) versus about 92 million monthly PyPI downloads (bleepingcomputer.com); the figures are broadly compatible but are measured over different periods.
- Second-stage exposure: Wiz says
domain.txtwas never populated and held only test values (wiz.io, thehackernews.com), and Socket saw the pointer empty in one observation (gbhackers.com), whereas SafeDep cannot rule out that hosts whose daemon ran earlier received second-stage code (safedep.io). - Link to the March TeamPCP attack: thehackernews.com notes the shared use of a
.pthfile with the March compromise, but Socket found no evidence linking the incidents and reports different RSA keys, exfiltration implementation and backdoor behavior (thehackernews.com). The most recent reporting does not establish attribution.
Linha do tempo
-
LiteLLM release pipeline compromised: PyPI 1.107.0 and Docker images distribute credential-stealing malware
ler a análise desta fonte ocultar
On October 21, attackers compromised the release pipeline of LiteLLM, an open-source Python SDK and AI gateway with about 92 million monthly PyPI downloads. They published malicious version 1.107.0 to PyPI, Docker Hub and GHCR. The payload steals cloud, AI, developer and browser credentials and loads remote-code execution tools. All seven wheels for 1.107.0 were affected on Windows, Linux and macOS. The maintainer says customers on the private enterprise offering were not impacted. Security vendors detected the attack within six minutes of publication. The project was previously breached in March by TeamPCP via the compromised Trivy scanner in its CI/CD pipeline.
Technical Details
- The attacker did not modify LiteLLM application code. Only the installation package was altered, to drop cook.pth, cook.py and sitecustomize.py into the Python library directory.
- Python executes
.pthlines and importssitecustomizeat startup, so the payload runs every time Python or pip is launched in the environment, including during investigation. - Targeted data: AWS, Azure, GCP, Kubernetes and Docker secrets; AI tool credentials and LiteLLM provider keys; Git, GitHub, npm, PyPI and CI/CD credentials; .env files; SSH, GPG and TLS keys; browser logins, cookies and autofill data; environment variables, shell histories and system/network information.
- Stolen data is encrypted with AES-256-CBC, with the key wrapped in RSA-4096, and uploaded to
litellm[.]dev/healthcheck. - sitecustomize.py starts a detached loader that polls a GitHub-hosted pointer hourly and downloads Python code from an external server for execution.
- Exposure windows (UTC): PyPI 11:39:51-13:23; Docker Hub tags v1.107.0, latest, main-latest and main-stable 11:46:56-14:20; GHCR same tags from 11:46:56 until removed by 13:51.
- Detection by Socket and Endor Labs, among other application security vendors.
Remediation
- Stop affected deployments and inspect environments without launching the Python interpreter.
- Isolate infected systems and rebuild from clean backups; deleting the LiteLLM package directory alone may leave startup files or an active loader.
- Rotate all exposed secrets immediately.
- Roll back to LiteLLM 1.106.2, the last clean release.
- Check for the three malicious files and the compromised image digests.
-
LiteLLM release pipeline compromised: malicious v1.107.0 on PyPI and Docker delivers credential stealer and RAT
ler a análise desta fonte ocultar
On October 21, 2026, attackers compromised the LiteLLM release pipeline and published malicious version 1.107.0 to PyPI, Docker Hub and GHCR. The package carried a credential stealer ("privcollect") and a backdoor that runs remote code every hour, effectively a RAT. LiteLLM suspects the attacker obtained developer GitHub CLI OAuth tokens from logs of an internal, publicly exposed LiteLLM deployment, where Claude Code responses had embedded the tokens. Wiz observed stolen AWS credentials validated about 4.5 hours after exfiltration, consistent with LLMjacking. Socket found no evidence linking this incident to the March 2026 TeamPCP attack, despite the shared use of a
.pthfile.Technical Details
- Exposure window: pip installs of unpinned versions between 11:39 and 13:23 UTC; Docker tags v1.107.0, latest, main-latest and main-stable (Docker Hub and GHCR) between 11:46 and 14:20 UTC.
- Stealer:
cook.pthimportscook.py, which deobfuscates itself and runs "privcollect". It collects system, browser, developer, cloud and AI tool secrets and exfiltrates them by HTTP POST tolitellm[.]dev/healthcheck. - Backdoor:
sitecustomize.py(Linux and macOS only) forks a daemon that holds/tmp/remote_code_loader.lock. Every hour it fetches the C2 domain from a GitHub dead drop (github[.]com/letters9813,pythonclient-test/main/domain.txt) and then downloads and executes a Python payload fromhttps://{domain}/codepy. Wiz reports the file held only test values before GitHub took it down around 13:30 UTC. Wiz also describes the combined .pth and sitecustomize.py technique as the first documented in the wild. - Intrusion chain:
- On October 19, LiteLLM temporarily expanded release permissions for two engineers.
- The attacker held three sets of developer GitHub CLI credentials, one able to run workflows.
- A token of a GitHub organization owner was used to disable branch protections and force-push changes.
- The workflow was pointed at the lookalike repository "Berri-AI/litellm" instead of "BerriAI/litellm", so the poisoned artifacts were signed and published.
- Initial access: how the internal deployment became public, and how the attacker got in, is unknown. LiteLLM theorizes a recently patched vulnerability.
- Post-exfiltration abuse (Wiz): AWS instance role credentials from CI runners and Kubernetes nodes were checked with sts:GetCallerIdentity, then bedrock:ListFoundationModels and ListModels. In a few environments the attacker also enumerated IAM (ListRoles, ListUsers, ListAccessKeys) and ran general discovery.
- Attribution: Socket notes the RSA public keys, exfiltration implementation and backdoor behavior differ from the March attack. No link is established, and the role of credentials stolen in March is unverified.
Remediation
- Remove LiteLLM 1.107.0, isolate affected hosts and hunt for the malicious artifacts (
cook.pth,cook.py,sitecustomize.py, the lock file). - Block the exfiltration domain, investigate execution of
/codepy, and rotate all reachable credentials. - Rebuild affected environments. Pin versions and verify the exact wheel before it reaches a build.
-
LiteLLM 1.107.0 PyPI wheels and container images compromised with credential-stealing malware
ler a análise desta fonte ocultar
LiteLLM version 1.107.0 was compromised in a supply chain attack that distributed credential-stealing malware through PyPI wheels and container images. On October 21, 2026, Socket reported that malicious Python startup hooks run even when an application never imports LiteLLM, exposing cloud credentials, developer secrets and AI tool authentication files. Socket flagged seven malicious wheels about seven minutes after publication, covering macOS, Linux and Windows. LiteLLM gets about 23 million weekly downloads, so the release sat close to sensitive production and development credentials.
Technical Details
- Container build provenance listed Berri-AI/litellm as the source instead of the legitimate BerriAI/litellm. The private BerriAI/project-releaser workflow showed a source-owner override selecting the hyphenated organization. The evidence does not show how the override was authorized, whether an account or token was compromised, or whether that workflow published the wheels.
- Build changes added
data = "cook"to the Maturin configuration and copied the malicious directory into Docker build stages. - Container tags v1.107.0, latest, main-latest and main-stable all resolved to the same image index, which widened exposure beyond pinned deployments.
- The wheels install
cook.pth,cook.pyandsitecustomize.pyinto Python's library directory. The startup hook runs during normal interpreter initialization, so starting Python or pip in an affected environment re-triggers the malware. - The decoded
privcollectpayload has 16 collection modules targeting AWS, Azure, Google Cloud, Kubernetes, SSH keys, browser databases, environment variables and developer configuration files. AI-specific targets include Codex, Claude, Gemini and Cursor. - A database module tries to read saved credentials and model settings from LiteLLM tables. There is no evidence of successful theft from individual deployments.
- Collected JSON is encrypted with AES-256-CBC, with the key wrapped using RSA-4096-OAEP, and uploaded to a deceptive
/healthcheckendpoint. sitecustomize.pylaunches a detached loader that reads a GitHub-hosted pointer and can run downloaded Python files without signature or hash verification. The pointer was empty in one observation, which blocked that stage but not the collector. The loader retries hourly, which does not confirm hourly exfiltration.
Remediation
- Block the release and inspect image digests, including the latest, main-latest and main-stable tags.
- Isolate environments where Python ran after installation, and preserve evidence with trusted tooling rather than the affected interpreter.
- Rebuild from reviewed artifacts and rotate potentially exposed credentials from a clean system. Removing LiteLLM alone neither reverses exposure nor stops an existing loader.
- Maintainers should validate repository identities, release permissions and published artifacts against approved sources.
-
LiteLLM PyPI and Docker supply chain compromise (v1.107.0) delivers credential stealer and RAT
ler a análise desta fonte ocultar
Unknown attackers compromised the release process of LiteLLM, the open source AI gateway developed by BerriAI, and distributed malicious version 1.107.0 through PyPI and Docker registries (Docker Hub and GHCR). The package carries an infostealer targeting cloud and AI credentials and a RAT that can execute arbitrary code. PyPI quarantined the version within hours and the Docker image
litellm/litellm:1.107.0was removed, but anyone who ran it should assume their secrets are stolen. LiteLLM gets about 23 million weekly downloads, and the scale of this incident is not yet known. An earlier LiteLLM compromise in March reportedly exposed more than 2,500 organizations and 434,000 CI/CD pipelines (per CloudSEK). BerriAI did not respond to The Register.Technical Details
- The malicious version was uploaded at 11:39 UTC. According to Wiz researchers, the payload came from malicious commits to
github.com/Berri-AI/litellm, a hyphenated lookalike of the legitimate BerriAI organization. This repo was used to inject three malicious files into the release pipeline. cook.pthmakes Python automatically runcook.pyon every interpreter invocation, with no user action.cook.pyis the infostealer, with 16 modules. It harvests browser credentials and cookies (Chrome, Firefox, Edge, Safari), AWS credentials (~/.aws/, environment variables, EC2/ECS IMDS), GCP service account keys and application default credentials, Azure CLI tokens, and API keys for OpenAI, Anthropic, Cohere and other LLM providers. It also takes SSH private keys, GPG keys and shell history.sitecustomize.pyis the RAT. It also runs at interpreter startup and spawns a background daemon that polls attacker infrastructure hourly for commands.- Stolen data is encrypted with AES-256-CBC, the key is wrapped with RSA-4096, and the blob is sent by HTTP POST to
http://www[.]litellm[.]dev/healthcheck. - Host indicators:
/tmp/.pc_once_*means exfiltration has fired;/tmp/remote_code_loader.lockmeans the C2 daemon ran or is still running (Aikido Security). - Affected images also include those pulled via the
latest,main-latestandmain-stabletags.
Remediation
- Stop deploying 1.107.0. The most recent safe version is v1.106.2.
- Investigate every environment where Python ran after installation, including proxy containers and CI runners.
- Check for the two
/tmpartifacts above. - Treat all secrets on affected hosts as compromised and rotate them: LLM provider API keys, cloud credentials, SSH/GPG keys and database connection strings.
- Follow the threat-hunting and mitigation guidance published by Aikido, Wiz and Socket.
- The malicious version was uploaded at 11:39 UTC. According to Wiz researchers, the payload came from malicious commits to
-
LiteLLM 1.107.0 PyPI and Docker Supply Chain Compromise Delivers privcollect Credential Stealer and Backdoor
ler a análise desta fonte ocultar
The widely used LiteLLM Python package was compromised in a software supply chain attack. Malicious version 1.107.0 was published via PyPI wheels and Docker images, delivering a credential stealer and a backdoor, per reports from SafeDep, Socket, StepSecurity and Upwind. LiteLLM says the release was pushed through three engineers' GitHub accounts, apparently using stolen GitHub CLI OAuth tokens. The initial token theft vector is still unknown. The package has been quarantined on PyPI and the malicious Docker images removed. The same
.pthexecution behavior was seen in the earlier TeamPCP-linked LiteLLM compromise in March.Technical Details
- Affected artifacts:
litellm-1.107.0wheels for macOS (x86_64, arm64), manylinux_2_28 (x86_64, aarch64), musllinux_1_2 (x86_64, aarch64) and Windows (win_amd64), plus the sdistlitellm-1.107.0.tar.gz(no payload files, but a tamperedpyproject.toml). - Attackers used one user's account to trigger the project-releaser run and another's to approve it.
- Execution occurs at interpreter start, before LiteLLM is imported, via the path file
cook.pthcontainingimport cook. - Payload 1, a stealer calling itself privcollect, harvests cloud tokens, developer accounts and private keys, AI tooling credential JSON files, Chromium and Firefox browser data, and environment variables. It also targets LiteLLM proxy saved credentials and model configuration.
- Stolen data is packed into a GZIP-compressed TAR and sent by HTTP POST to
litellm[.]dev/healthcheck. - Payload 2 forks a background daemon that checks a GitHub dead drop hourly: it reads
domain.txtingithub[.]com/letters9813, reruns the stealer if a domain is present, then fetches<domain>/codepyvia HTTP GET and executes the response. The repository now returns 404.
Remediation
- Revoke and replace all credentials exposed on systems that installed 1.107.0, working from a clean environment.
- Pin LiteLLM to version 1.106.2 by digest.
- LiteLLM revoked all involved tokens, removed all but one unaffected user from its GitHub organization, and removed trusted links to its GitHub organization from the public registries. It cannot yet rule out further access to the affected accounts.
- Affected artifacts:
-
LiteLLM PyPI package and Docker images trojanized (v1.107.0) with credential stealer and persistence hooks
ler a análise desta fonte ocultar
On October 21, a malicious LiteLLM version (1.107.0) was uploaded to PyPI. Trojanized Docker images on GHCR and Docker Hub (tags v1.107.0, latest, main-latest, main-stable) were also published. The payload was injected through malicious commits in github.com/Berri-AI/litellm, a hyphenated lookalike of the legitimate BerriAI organization, which fed the release pipeline. The package installs a stealer, internally named privcollect, that harvests browser, cloud, developer and AI provider secrets and exfiltrates them to the attacker-controlled domain www.litellm[.]dev. The PyPI version was quarantined and the Docker tags removed at about 13:53 UTC. The last known safe version is v1.106.2.
Technical Details
- Installation drops cook.pth, cook.py and sitecustomize.py into the site-packages root, so the code runs whenever a Python interpreter starts. The .pth file imports
cook, which deobfuscates itself, runs the stealer and writes a marker file at/tmp/.pc_once_72129118c59f5636c0bb. The marker write fails on Windows. - privcollect has 16 modules. It collects Chrome, Firefox, Edge and Safari credentials and cookies, AWS credentials (
~/.aws/, environment variables, EC2/ECS IMDS), GCP service account keys and ADC, Azure CLI token cache, API keys for OpenAI, Anthropic, Cohere and other LLM providers, SSH and GPG keys, and shell history. - On LiteLLM Proxy hosts it queries PostgreSQL directly with
SELECT * FROM "LiteLLM_CredentialsTable" LIMIT 500to dump upstream provider keys. - Data is encrypted with AES-256-CBC (key wrapped with RSA-4096) and sent by HTTP POST to
www.litellm[.]dev/healthcheckwith a hardcoded X-Token header and an Internet Explorer 7 user-agent. - sitecustomize.py runs on Linux and macOS only. It fetches
domain.txtfrom a GitHub dead drop (letters9813/pythonclient-test) and, if populated, downloads and runs a second-stage Python script fromhttp://<domain>/codepy. The file was never populated at the time of analysis, and the repo was taken down. - Between 08:56 and 10:46 UTC the attacker pushed 10 commits using the email [email protected]. The first nine were GitHub-signed, added the persistence files, bumped the version and added
data = "cook"to pyproject.toml so the malware is bundled into the wheel. A final unsigned commit under [email protected] addedCOPY cook ./cookto the Dockerfiles. The commits remain visible via the parent repo through fork object sharing (compare a8113b0d...20535d8f).
Remediation
- Identify any host or container that installed or pulled LiteLLM 1.107.0 or the affected Docker tags, and pin to v1.106.2.
- Search for cook.pth, cook.py, sitecustomize.py and the
/tmp/.pc_once_*marker, and hunt for traffic to litellm[.]dev. - Treat all secrets on affected systems as compromised and rotate them: cloud credentials, LLM provider API keys, keys in the LiteLLM_CredentialsTable, SSH/GPG keys and browser sessions.
- Rebuild affected images and environments from known-good sources.
- Installation drops cook.pth, cook.py and sitecustomize.py into the site-packages root, so the code runs whenever a Python interpreter starts. The .pth file imports
-
LiteLLM 1.107.0 PyPI wheels and Docker image trojanized with infostealer and persistent Python RAT
ler a análise desta fonte ocultar
On October 21, 2026, LiteLLM version 1.107.0, a widely used open source LLM proxy, was found to be compromised. An attacker injected malicious code into the compiled Python wheels published on PyPI, and the official Docker image litellm/litellm:1.107.0 is also affected. The package carries an infostealer that exfiltrates credentials and secrets on first run, and a RAT that lets the attacker execute arbitrary Python on infected hosts every hour. PyPI has quarantined the version, but the Docker image was still live on Docker Hub at the time of reporting. Anyone who installed this version should assume credentials are compromised.
Technical Details
- The attacker abused the
[tool.maturin] data = "cook"directive inpyproject.tomlto bundle acook/directory, which exists only in the compromised build environment and not in the source repo, into every wheel. - Three files are dropped into site-packages:
cook.pth(12 bytes,import cook, runs at every interpreter start),cook.py(the infostealer, a single obfuscated line that decompresses and executes a 61,000-byte payload), andsitecustomize.py(the RAT). - The infostealer collects system information, Chromium and Firefox credentials and history, SSH keys, shell history, AWS/Azure/GCP credentials (including instance metadata endpoints), Docker and Kubernetes secrets, CI/CD secrets (GitLab runner, Jenkins, Vault), AI developer tool configs (Claude Code, Cursor, Copilot, Windsurf, Gemini CLI and others), Git/npm/PyPI credentials, GPG/TLS keys, and all environment variables (including
/proc/<pid>/environon Linux). It also dumps LiteLLM_CredentialsTable and LiteLLM_ProxyModelTable from the LiteLLM database. - Data is encrypted with a hardcoded RSA-4096 public key and sent by HTTP POST to
http://www[.]litellm[.]dev/healthcheck. The sentinel file/tmp/.pc_once_72129118c59f5636c0bblimits it to one run per machine. - The RAT forks a daemon that takes the lock
/tmp/remote_code_loader.lock. Every hour it fetches the current C2 domain fromraw[.]githubusercontent[.]com/letters9813/pythonclient-test/main/domain[.]txt, then downloads andexecs Python fromhttp://{domain}/codepywith no sandboxing. - Network indicators: HTTP POST with User-Agent
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0)and headerX-Token: XWiA8gZNa7NcX2XRoAEb.
Remediation
- Check for
/tmp/.pc_once_*(exfiltration already fired) and/tmp/remote_code_loader.lock(C2 daemon ran or is running) on any host that installedlitellm==1.107.0or ranlitellm/litellm:1.107.0, including thelatest,main-latestandmain-stabletags. - Treat all credentials, API keys, SSH/GPG/TLS keys, cloud and CI/CD secrets reachable from affected hosts as compromised and rotate them.
- Remove the affected version and image, hunt for
cook.pth,cook.pyandsitecustomize.pyin site-packages, and block the listed domains and the GitHub C2 lookup path. - Rebuild affected hosts or containers from known-good sources.
- The attacker abused the
-
Compromised LiteLLM 1.107.0 on PyPI Drops Credential Stealer and Remote Code Backdoor via Python Startup Hooks
ler a análise desta fonte ocultar
The LiteLLM 1.107.0 release on PyPI was trojanized with a credential stealer and a remote code execution backdoor. All seven wheels (Linux, macOS, Windows) install three extra files in site-packages, and two of them run whenever any Python process starts, even one that never imports litellm. The malicious code is not in the upstream GitHub source, and PyPI has since removed the release. SafeDep assesses with moderate to high confidence that BerriAI's private release pipeline built the wheels from attacker-modified git source. The exact cause (compromised maintainer or bot credential, private branch or mirror, or the build reference) can only be confirmed from BerriAI's pipeline logs. Versions 1.106.2, 1.107.0rc1 and 1.107.0rc2 are clean, as are the pinned companion packages litellm-proxy-extras==0.4.110 and litellm-enterprise==0.1.78.
Technical Details
- Injection: the sdist
pyproject.tomlhas one extra line in the maturin section,data = "cook". It copies acook/folder (absent from the sdist) intolitellm-1.107.0.data/purelib/, and pip installs it into site-packages. No public commit in BerriAI/litellm contains it. - Tag mismatch: tag v1.107.0 (commit 66c8f5b) declares version 1.108.0. The sdist matches a later main commit (a8113b0) plus edited files. The version was reset to 1.107.0 and the companion pins were set to the rc2 values, so a dependency diff against rc2 shows nothing unusual.
- Build provenance: the wheels were built with maturin 1.9.4, like the legitimate releases, with separate native builds on macOS, Linux and Windows. SafeDep checked 539 public GitHub Actions runs and found none that built the release, and PyPI has no provenance attestations for these versions.
- Payload 1,
cook.pth/cook.py:cook.pthcontainsimport cook, so the stealer runs in every Python process (applications, pip, IDE language servers, CI jobs). The zlib/base64-packed code collects SSH keys, cloud credentials, CI/CD secrets, AI tool tokens, browser passwords and history, shell history, GPG keys, TLS private keys, cloud metadata and the LLM provider keys in a LiteLLM proxy database. Results are encrypted with AES-256-CBC, the key is wrapped with RSA-OAEP (RSA-4096), and the tar.gz is POSTed towww.litellm[.]dev/healthcheckwith anX-Tokenheader. A marker file limits collection to once per host. - Payload 2,
sitecustomize.py: it takes a lock file, forks and detaches a daemon, and every hour reads a domain fromdomain.txtin the attacker's GitHub repository, re-runs an embedded stealer copy with no once-per-host marker, and downloads andexec()s code fromhttp://<domain>/codepy. - Takedown: at 13:40 UTC on 2026-10-21 the GitHub account letters9813 and its repository returned 404, so the backdoor currently finds no server address. Hosts whose daemon ran earlier could have received second-stage code. SafeDep could not recover the server address.
Remediation
- Check for litellm==1.107.0 in environments, lockfiles, containers and CI caches. Treat any host that installed it as compromised.
- Look for
cook.pth,cook.pyandsitecustomize.pyin site-packages,/tmp/.pc_once_72129118c59f5636c0bb,/tmp/remote_code_loader.lock, and traffic to litellm[.]dev. - Rotate all credentials reachable from affected hosts: SSH keys, cloud and CI/CD secrets, AI tool tokens, LLM provider keys and browser-stored passwords.
- Because second-stage code may have run, consider rebuilding affected hosts. Pin known-good versions (1.106.2 or 1.107.0rc2).
- Injection: the sdist