Security News

LiteLLM’s Dead Drop Explained: Infected Hosts Still Poll a Deleted Account

StepSecurity says LiteLLM 1.107.0's loader polls a deleted GitHub account every hour. Learn what a dead drop resolver is and how to stop the loader.

Brandefense logo 5 Min Read
Neon red mailbox with cracked glow and data stream representing cyber security.

Last updated 26 October 2026, from StepSecurity’s analysis and LiteLLM’s own incident pages.

The loader hidden in LiteLLM 1.107.0 does not carry its instructions. Once an hour it reads a file in a GitHub repository to learn which server to fetch code from. StepSecurity says the account that owned that file was deleted, but infected hosts keep asking for it. That design has a name, the dead drop resolver, and it explains why removing the bad package is not the end of the clean-up.

This post explains the technique and what is known about LiteLLM’s dead drop. For the full timeline and the response checklist, see our LiteLLM 1.107.0 response checklist and the incident profile.

What Is a Dead Drop Resolver?

MITRE describes a dead drop resolver as content posted on a legitimate web service that points infected hosts to additional command and control infrastructure. The content often carries an embedded and obfuscated domain or IP address. The malware reads the page, learns where to connect and follows. Our Dead Drop Resolver technique page covers the ATT&CK entry, T1102.001.

Definition: Why attackers like itMITRE says popular sites give cover because hosts already talk to them. It also says the back-end infrastructure may be dynamically changed.

How Did LiteLLM’s Loader Use One?

The wheels installed a startup file, sitecustomize.py, next to cook.pth. Per StepSecurity, the file forks a detached background process on Linux and macOS. Every hour that process reads a hostname from a file on raw.githubusercontent.com, downloads code from that host at the path /codepy and runs it with exec(). On Windows the loader fails silently because the calls it needs are missing, while the credential stealer still runs.

Sequence diagramSequence diagram with 3 actors (Infected host, GitHub file, Attacker server) and 2 messages: 1, Infected host to GitHub file: Reads the file every hour; 2, Infected host to Attacker server: Requests /codepy.Infected hostGitHub fileAttacker server1. Reads the file everyhour2. Requests /codepy
  1. 1Infected host GitHub fileReads the file every hour
  2. 2Infected host Attacker serverRequests /codepy

The path is the part to remember. StepSecurity says any request to /codepy means remote code ran. The same page says the file was empty when the release went out, so the second stage was not armed. It also says no second-stage payload was observed through the dead drop.

Our Python Startup Hooks page explains how the startup file got to run at all.

Why Does a Deleted Account Still Matter?

The preparation began days before the release. StepSecurity dates the registration of litellm.dev to 13 October and the creation of the GitHub account about six hours later. The file held three different values before the release.

The dead drop before the release
  1. 13 Oct 2026litellm.dev registered; GitHub account created about six hours laterStepSecurity
  2. 18 Oct 2026Dead drop repository created; file points to localhost:18909StepSecurity
  3. 19 Oct 2026File points to test.test.com:18909StepSecurity
  4. 20 Oct 2026File is empty and stays empty at release on 21 OctoberStepSecurity

StepSecurity says the account has since been deleted, yet infected hosts keep polling the address. It warns that re-registration of that username would allow code execution on hosts that are still infected.

The point for defenders is that a dead address is a risk only while some host still asks for it, and the number of such hosts is unknown.

StepSecurity counts about 49,000 PyPI downloads of the bad version before removal, a figure that includes CI caches and mirrors and leaves out container pulls. Downloads are not infections.

In the underground chat and forum sources we monitor we counted 104 posts that mention LiteLLM from 21 to 26 October 2026, 93 of them on Telegram. The counts do not tell us who has the stolen data or what was done with it.

How Does the Unrevoked Key Fit In?

The dead drop is the last link of a longer chain. LiteLLM’s own attack chain post says a master key was committed on 27 May 2026 and that “key revocation did not occur for the master key”. StepSecurity says it kept working for almost five months, and that on 10 October it returned a GitHub CLI token that belonged to an organization owner.

StepSecurity credits Lidor Machluf of Upwind with the public report in GitHub issue 47826. The release is the visible part of the attack. A leaked key that stays valid is what let it begin, which is why our checklist puts revoking exposed credentials next to rotation.

What Should You Do About the Loader?

Treat a host that ran 1.107.0 as one that is still polling until the loader is stopped. Pinning an older version does not stop a process that is already running.

Stop the dead drop from working
  • Stop the processEnd the process that holds /tmp/remote_code_loader.lock before running pip.
  • Delete the startup filesRemove cook.pth, cook.py and sitecustomize.py and the matching cached bytecode.
  • RebuildRebuild environments and images from scratch and pin a clean release. StepSecurity names 1.106.4 and the backports 1.105.5, 1.104.7 and 1.103.9.
  • Rotate and revokeRotate every credential the host could reach from a clean machine.
  • Block and alertBlock litellm.dev at DNS or egress and alert on raw.githubusercontent.com/letters9813/ and on any /codepy request.

LiteLLM’s releases page shows v1.106.3 on 24 October and v1.106.4 on 25 October 2026, which matches the clean releases StepSecurity describes. StepSecurity also says images are signed with a new cosign key from v1.106.3, so update your verification before you rely on the signature. For the wider hunt through cloud logs, use the response checklist. The attack also sits in the wider pattern of software supply chain compromise.

The lesson for your own network is simple. A fetch from a script to a raw file on a code host, on a timer, is worth an alert. MITRE’s advice is to restrict web content your hosts do not need and to detect scripts that retrieve content from common web services.

Frequently Asked Questions.

Which address does the LiteLLM loader poll?

Per StepSecurity, a file named domain.txt in a GitHub repository of the account letters9813, read through raw.githubusercontent.com every hour. The account is deleted, but infected hosts keep polling the address.

Am I still at risk if I upgraded LiteLLM?

Possibly. StepSecurity's steps say to stop the process that holds /tmp/remote_code_loader.lock, delete cook.pth, cook.py and sitecustomize.py, and rebuild. Changing the installed version alone does not stop a running loader.

Does the loader run on Windows?

StepSecurity says it fails silently on Windows because fcntl and os.fork are missing, while the credential stealer can still run and may rerun on every start.

Was a second-stage payload ever delivered?

StepSecurity says no second-stage payload was observed through the dead drop, and that the file was empty at release. It also says infected hosts keep polling the address.

Sources

  1. 1 StepSecurity, litellm 1.107.0 Compromised on PyPI and Docker: Credential Stealer and Hourly Remote Code Loader
  2. 2 LiteLLM, Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised
  3. 3 LiteLLM, root cause analysis and attack chain of 23 October 2026
  4. 4 MITRE ATT&CK, Web Service: Dead Drop Resolver, T1102.001
  5. 5 BerriAI/litellm on GitHub, releases
Share