Cybersecurity

The litellm Supply Chain Attack: How One pip install Could Have Hijacked Your Entire Infrastructure

litellm, pulled 97M times a month, shipped malware that ran without an import. Only its own bug stopped silent theft of SSH keys and cloud credentials.

The litellm Supply Chain Attack: How One pip install Could Have Hijacked Your Entire Infrastructure

As engineers and system architects, we work every day on the assumption that the open-source ecosystem can be trusted. Running pip install has become as automatic as breathing. It happens thousands of times a day on hundreds of thousands of machines, and nobody thinks twice about it. On March 24, 2026, that foundation of modern software engineering was badly shaken.

The victim was litellm, a key library in the AI world that is downloaded nearly 97 million times a month. Two malicious versions, 1.82.7 and 1.82.8, appeared on PyPI without going through the project's normal CI/CD pipeline. The attackers uploaded them directly and left no trace on GitHub, with no tags and no releases. Worse, the infected code spread through transitive dependencies to every system that installed popular packages such as dspy or MCP plugins for the Cursor editor.

As architects, we have to ask ourselves: do we really know what happens in our environment after we hit Enter?

The .pth File: Invisible Activation Without a Single Import

The most alarming part of version 1.82.8 was its use of a file called litellm_init.pth. Developers tend to assume that malicious code in a library only becomes dangerous once it is imported. This attack proved that assumption wrong.

.pth files (path configuration files) are processed by the site module when the Python interpreter starts up. They were designed to add directories to sys.path, but they can also run arbitrary code through exec(). For an attacker, that is the holy grail of persistence: as long as the file sits in site-packages, the malicious code runs automatically every time the interpreter starts.

"The malicious code runs completely automatically every time the Python interpreter starts. You don't even need to import the litellm library."

Installing the package was enough. From then on, the malware activated whenever any Python script ran on that machine, even one with no connection to litellm at all. That completely destroys the "I'm safe because I don't use that library" defense.

Two Versions, Two Approaches: Stealth vs. Brute Force

The attack came in two distinct forms, and the difference tells us a lot about how the attackers worked.

Version 1.82.7 was subtle. It had no .pth file. Instead, it hid the payload inside proxy/proxy_server.py, and the malicious code only activated when the litellm proxy server was started. In other words, it targeted production environments where the library was doing real work every day. It was a quiet, surgically precise attack.

Version 1.82.8 aimed for a total takeover. Its .pth mechanism automatically infected every environment the package landed in, from a developer's laptop to a CI/CD server. The two versions suggest the attacker was experimenting with different infection methods, moving from quiet infiltration to aggressive takeover.

If your audit checks for only one of these versions, your SOC team may get a false sense of security.

A Fork Bomb: When a Hacker's "Vibe Coding" Saves Thousands of Machines

The world learned about the attack just one hour after the malicious package was published, and that was only because the attackers made a mistake. Their code contained a critical logic error.

The .pth file called subprocess.Popen to start a background process that would steal data. But every new Python process loaded the same .pth file again, so the system fell into a recursive loop of process creation: a classic fork bomb. Instead of quietly exfiltrating data, the malware ate up all available RAM and CPU within moments and crashed the machine.

Callum McMahon of FutureSearch found the attack precisely because engineers using Cursor and MCP plugins (which pull in litellm) started reporting widespread, unexplained system freezes. Had the code been written correctly, the malware could have sat in environments for weeks, quietly draining secrets from thousands of companies. The irony is that the hackers' poor craftsmanship is what saved the community.

A Credential Vacuum: What Exactly Were They After?

Analysis of the payload shows a frightening precision in its choice of targets. The malware was built to vacuum up everything of value on a machine running modern infrastructure. The stolen data was packed into an archive called tpcp.tar.gz, encrypted with AES-256-CBC (with the session key protected by 4096-bit RSA), and sent out in the background using curl.

The shopping list included:

  • Core access: SSH keys (id_rsa, ed25519), Git configurations, shell history (.bash_history, .zsh_history), private SSL/TLS keys from /etc/ssl/private/, and Let's Encrypt certificates.
  • Cloud and CI/CD infrastructure: Full AWS credentials (including IMDS tokens), GCP (Application Default Credentials), and Azure. Particularly dangerous: it also scanned for terraform.tfvars, .gitlab-ci.yml, Jenkinsfile, and ansible.cfg.
  • Kubernetes and containers: Cluster configurations (~/.kube/config), service account tokens, and Docker and Kaniko secrets.
  • Finance and communications: Cryptocurrency wallets (from Bitcoin through Ethereum and Solana to Cardano), plus Slack and Discord webhook URLs pulled from environment variables (printenv).

Lateral Movement: Spreading into Kubernetes Clusters

The attack didn't stop at the local machine. The malware could recognize a Kubernetes environment. If it found a service account token, it tried to read cluster secrets across all namespaces.

To stay in place, the malware tried to create privileged pods named node-setup-* in the kube-system namespace, using the alpine:latest image. These pods mounted the host file system and installed a backdoor at /root/.config/sysmon/sysmon.py. The name sysmon was chosen on purpose to look like a legitimate system monitoring tool, a classic way to blend in on Linux.

If your K8s cluster had any contact with an infected environment, treat it as compromised.

A Lookalike Domain and Sabotage on GitHub

The attack went beyond code. It was backed by a carefully planned disinformation campaign.

Data was exfiltrated to the domain models.litellm.cloud. To a tired engineer, that looks like official infrastructure, but the project's real domain is litellm.ai. The difference is subtle, and it works.

GitHub was even worse. When users opened issue #24512 to warn about the malware, it was abruptly closed as "not planned," most likely by a compromised maintainer account. Moments later, the discussion was flooded by hundreds of bots posting generic comments like "Thanks, that helped!" and "Great explanation!" This was a deliberate disinformation operation meant to bury the warnings under a pile of digital noise and stall the incident response.

It is a textbook example of modern information warfare waged inside the open-source community.

Action Plan: What You Need to Do Now

If AI libraries were installed in any of your environments (local, CI/CD, or production) around March 24, 2026, take these steps:

  1. Check the version: Run pip show litellm. If you see 1.82.7 or 1.82.8, the system is infected.
  2. Clear every cache: Run pip cache purge and, critically, rm -rf ~/.cache/uv if you use the uv tool.
  3. Find the artifacts: Look for the litellm_init.pth file in site-packages. Check for a ~/.config/sysmon/ folder and a sysmon.py file.
  4. Look for persistence: Check whether a new systemd service has been registered at ~/.config/systemd/user/sysmon.service.
  5. Inspect your K8s clusters: Look for pods named node-setup-* in the kube-system namespace. If they are there, the cluster has been compromised at the node level.
  6. ROTATE EVERYTHING: This is the most important step. If you found any sign of infection, treat all SSH keys, cloud credentials (AWS/GCP/Azure), API tokens, and database passwords as compromised and rotate them immediately. Removing the library won't change the fact that the attacker already has your secrets.

The End of Unlimited Trust

The litellm incident is a warning we cannot afford to ignore. In today's frantic AI arms race, supply chain security has become our biggest weakness. The traditional architecture built from thousands of dependency "bricks" is a minefield. If just one brick near the bottom of the foundation is poisoned, the whole structure becomes a weapon pointed at the people who built it.

A sensible architectural strategy is increasingly what some call "yoinking." Instead of adding yet another heavy dependency for a single function, use an LLM to generate clean, local code that does the same job. That shrinks your attack surface and gives you back control over what your interpreter actually runs.

When did you last check exactly what your next dependency installs?

Aleksander

AuthorAleksander Zębrowski

Read more

Related articles

Want to know if this affects your company?

A free consultation with one of our experts — no obligation, in full confidence.

Let's talk