LiteLLM is a popular open source Python library that sits between an application and AI providers such as OpenAI and Anthropic. A lot of AI-powered apps use it, or something like it, so that they can swap models without rewriting their code. Last Wednesday a poisoned version of it was published to PyPI and Docker Hub.

What happened, in LiteLLM's own words

LiteLLM published its postmortem on 23 October. It's unusually open, and worth reading in full if you run anything that touches it. The short version goes like this.

  • On 27 May, a configuration file containing the master key for an internal tool was committed to a public GitHub repository.
  • The commit was removed, but in the postmortem's words, "key revocation did not occur for the master key."
  • On 10 October, someone used that key to reach the internal platform and pull out a GitHub token belonging to an organisation owner.
  • Over the following days that access was used to collect more secrets and get round the release controls.
  • On 21 October, version 1.107.0 was published to PyPI and to Docker Hub and GitHub's container registry.

PyPI quarantined it in under two hours. Wiz, the security firm, says it was still downloaded roughly 49,000 times in that window. According to Wiz, the malicious code went after browser passwords and cookies, cloud credentials for AWS, Google Cloud and Azure, and API keys for AI providers.

LiteLLM's own summary is that the incident shows the risk of "failing to rotate a potentially exposed key". More than four months passed between the key going public and the attack starting. That's four months in which changing one value would have closed the door.

First, are you affected?

If you or your developer use LiteLLM, check this before you read anything else. LiteLLM's incident post says to pin to version 1.106.2 or another explicit version published before the incident, and to avoid 1.107.0 completely. Running pip show litellm will tell you which version is installed. The Docker tags affected were v1.107.0, latest, main-latest and main-stable.

If 1.107.0 ran anywhere with internet access, LiteLLM's advice is to assume data left the building. That means cleaning or rebuilding the environment (rebuilding from scratch is their preference), then rotating every credential that machine could reach. That includes the AI provider keys stored in the LiteLLM proxy database, cloud access roles, database passwords and anything sitting in environment variables. Follow their incident post step by step rather than my summary of it, because the order matters. Running pip in an infected environment can set the malicious code off again.

Why deleting isn't enough

This is the part that applies to everyone, whether you've heard of LiteLLM or not.

When a secret is pushed to a public repository, you have no way of knowing who copied it while it was there. Git keeps history. People clone and fork repositories. Automated scanners trawl public code looking for exactly this sort of thing. Removing the commit tidies up your repository, but every copy that already exists stays exactly as it was.

The only fix that actually works is to make the old key useless. Revoke it, issue a new one, update whatever uses it. Done properly that's often ten minutes' work. Not done, it's a door left open for as long as the key stays valid.

The same goes for keys pasted into a support ticket, a Slack channel, an email to a freelancer or a prompt to an AI assistant. If it's been somewhere you don't control, treat it as seen.

What to check in your own business

You don't need a security team to get the basics right. Here's what I'd look at this week.

  • Know where your keys live. Make a simple list of every API key, token and password your systems use: Stripe, Shopify, OpenAI, your hosting, your database. Who has access to each, and when was it last changed?
  • Keep keys out of code. Secrets belong in environment variables or a proper secrets manager, not in config files that get committed. GitHub's secret scanning is worth switching on if you host code there.
  • Give tokens the least access they need. The LiteLLM postmortem notes the stolen GitHub token "was not scoped down". A token that can only do one job does a lot less damage when it leaks.
  • Pin your dependencies. If your app installs "the latest version" of a package every time it builds, a poisoned release can walk straight in. Pinned versions and lock files mean you choose when to upgrade.
  • Have a rotation plan. If you had to change every key tonight, could you? If the honest answer is "I'm not sure what would break", that's worth sorting before you need it.

None of this is glamorous. It's housekeeping, the same as testing your backups. But it's the housekeeping that decides whether a slip-up stays a slip-up.

A word on AI-built apps

If your app was put together quickly, with an AI tool or by a developer in a hurry, it's worth checking specifically where the keys ended up. When the priority is getting the code to run, it's easy for a key to land in the wrong place, and nobody may have looked since. We've written a security checklist for AI-built apps that covers this and eleven other things to look at.

If you'd rather someone else looked, our AI code audit is a fixed-price written review of one system, covering access, hosting and backups, with a price for each fix. And if you want someone looking after this sort of thing month to month, rather than once, that's what our outsourced tech department is for.

The takeaway

Credit to LiteLLM for publishing such a detailed account. Most organisations never say this much, and the rest of us get to learn from it without paying the price.

The lesson is a simple one. If a key has been exposed, even for a minute, even if you deleted it straight away, change it. Today, not when you get round to it.

If you're not sure where your keys are or whether any have leaked, get in touch and we'll have a look with you.

Cheers, Rob