A release of the LiteLLM Python package published to PyPI on October 21 carried a credential stealer and a remote-access backdoor. Installing version 1.107.0 placed three files in the site-packages folder. Two of them ran every time any Python process started on the machine, including processes that never touched LiteLLM. PyPI has since removed the release.
SafeDep, the security firm that analyzed the package, said the upstream GitHub source does not contain the malicious files. Versions 1.106.2, 1.107.0rc1 and 1.107.0rc2 are clean, and so are the companion packages that 1.107.0 depends on.
What did the malicious LiteLLM 1.107.0 release steal?
The first file, cook.pth, tells Python to import a second file, cook.py. That file is a credential stealer. According to SafeDep, it collects SSH keys, cloud credentials, CI/CD secrets, AI tool tokens, browser passwords and the LLM provider keys stored in a LiteLLM proxy database. It encrypts the haul and uploads it to www.litellm[.]dev.
The third file, sitecustomize.py, starts a background process that wakes up every hour. It reads a server address from a file in a GitHub repository, runs the stealer again, then downloads and executes whatever code that server returns. The GitHub account and repository were deleted about two hours after the release went up, and at the time SafeDep checked, the backdoor had no server address to contact. Hosts that ran the process before the deletion could have received and run second-stage code. SafeDep said it could not recover the server address.
How the malicious code got into the release
How did malicious code get into the PyPI release?
The problem started in the source distribution, the package archive that pip can build from. Its pyproject.toml file contains one line that does not appear in the public repository: a data setting that copies a folder named cook into the wheel. The source archive leaves that folder out, so the extra line is the only visible sign of the change.
The release also did not match its own tag. The v1.107.0 tag points to a commit that lists version 1.108.0 in its project file. SafeDep found that the archive matched a later commit on the main branch, with five edited files and the added folder. The edits set the version back to 1.107.0 and pinned the companion packages to the values used in the earlier release candidate, which kept a dependency comparison against rc2 from showing anything unusual.
The malicious wheels were built to look like normal output from the project's release process. They list the same build tool version as legitimate releases, and their file records show no changes after the build. No public GitHub Actions run built or published the release. SafeDep checked 539 runs between 09:30 and 12:30 UTC and found none that produced it. The GitHub release was created about 10 minutes after the PyPI upload, by a bot account, and the same delay occurred with version 1.106.2. PyPI has no provenance attestations for 1.107.0, 1.106.2 or rc2.
SafeDep said, with moderate to high confidence, that the project's private release pipeline built the wheels from an attacker-modified source. It said a compromised maintainer or bot credential, a private branch or mirror, or the reference the pipeline builds from could all explain the evidence. A stolen PyPI token used from the attacker's own machines fits less well. Only the project's pipeline logs can confirm how it happened.
What the stealer targets
The stealer runs in every Python process on an infected host, including applications, pip, IDE language servers and CI jobs. It is organized into modules. One reads Chromium and Firefox saved passwords and browser history. Others target ~/.ssh keys, shell history, AWS, Azure, Google Cloud and Kubernetes credentials, GitLab runner and Jenkins secrets, and Terraform credentials. Another module looks for tokens and configuration files used by AI coding tools, including Claude Code, Cursor, Windsurf, Copilot and Gemini CLI, along with Hugging Face tokens.
The database module is especially sensitive for teams running LiteLLM as a proxy. It reads the database connection string and dumps the tables that hold the LLM provider API keys. The stealer also queries the AWS instance metadata service to pull instance identity and role credentials, and it reads environment variables from other running processes.
What should users do if they installed litellm 1.107.0?
Anyone who installed litellm 1.107.0 should assume that credentials on those machines may have been taken. SafeDep lists the indicators of compromise, including the upload domain, the planted file names and their hashes, and a marker file in /tmp that shows the stealer has already run on a host. Users who have the three files in site-packages should remove them and rotate every credential the host could reach.
Este artigo foi escrito com a assistência de IA.
News Factory APP - notícias agênticas para impulsionar seu SEO e AEO.
