The LiteLLM 1.107.0 container build recorded a lookalike source_owner, Berri-AI, in its attached provenance. Socket’s inspection found that three startup files in the recorded source revision matched files in a poisoned PyPI wheel byte for byte. The intended source_owner is BerriAI, without the hyphen. Release engineers have an immediate comparison to make: the source owner their pipeline was meant to build versus the owner it actually selected, and the wheel contents it published.
The seven 1.107.0 wheels carried a credential collector and a remote Python loader. They reached Python environments on developer machines, CI runners and LiteLLM proxy hosts where provider, cloud and developer credentials may be available. StepSecurity’s separate wheel inspection also found the same three files in affected containers; it reports that BerriAI removed the PyPI release and infected images. Socket puts LiteLLM at approximately 23 million weekly downloads across all versions. Scope this release by 1.107.0 installations and historical image digests, rather than applying that product-wide count to affected systems. The release cleanup changes what can be pulled now. Environments that installed or ran those artifacts still need investigation.
The build selected another owner
Socket compared attached provenance for the Linux amd64 image with the preceding v1.106.2 release. The v1.107.0 document names the private BerriAI/project-releaser workflow, run 39587059944, and commit 20535d8fa11f786a6c24df7488a0e449ed5f09ad. Its dispatch input records source_owner as Berri-AI; the preceding release records the intended BerriAI source. Socket puts the malicious container build between 10:51:23 and 11:06:31 UTC on October 21.
That source revision contains cook/purelib/cook.pth, cook/purelib/cook.py and cook/purelib/sitecustomize.py. Socket compared all three with the inspected wheel and found byte-for-byte matches. At 09:48:21 UTC, a commit in that revision added data = "cook" to Maturin’s build configuration, placing the directory into wheel data. A later change copied cook into backend, gateway and migrations image build stages. The three files crossed from the selected source into actual distributions, while an inspection of the ordinary tagged source alone would miss that addition. As Socket puts it, “The tagged release’s pyproject.toml lacks the added data setting.”
The provenance records the image builder’s stated inputs; compare those inputs with your approved repository and the published artifact. The wheel comparison independently identifies the packaged files. For the PyPI upload path, trace the publisher credentials and release run records in your own systems rather than treating an image’s provenance as a receipt for every distribution.
A wheel changes Python startup
Wheel installation puts the three files at the top of Python’s site-packages, outside the litellm/ package directory. Python’s site initialization documentation describes how executable .pth import lines run during startup and how sitecustomize is imported afterward. Here cook.pth imports cook.py, starting a background collector. sitecustomize.py supplies a separate loader. Importing LiteLLM is unnecessary; an interpreter launched to inspect or repair the environment can run the hooks again.
Socket’s static analysis found that the collector targets cloud credentials, AI-tool authentication files and, on Linux, other readable processes’ environments. When DATABASE_URL is configured, its database module attempts to query LiteLLM proxy credential and model tables; Socket found the inspected macOS artifact fails its Linux /proc check before querying them. The collector encrypts what it gathers and posts it to hxxp://www[.]litellm[.]dev/healthcheck with header X-Token: XWiA8gZNa7NcX2XRoAEb. The separate loader consults a mutable GitHub-hosted pointer and, when it supplies a destination, retrieves Python from /codepy for execution. Socket observed that pointer empty at 13:01:44 UTC on October 21; the collector operates independently of it. StepSecurity reports the tag’s source tree was clean and the source distribution had the altered build setting but lacked the three payload files. Inspect the installed wheel or image, rather than inferring its safety from the tag or source archive.
Compare the shipped bytes
For release owners, compare the expected source owner, revision and workflow definition with the dispatch inputs for run 39587059944, then compare the built distributions with the approved tree. Treat a changed source_owner as a release-blocking mismatch, even when the build has provenance or a valid signature. Require an approved repository identity and reviewed revision before publishing credentials can be used. StepSecurity reports BerriAI restored its release workflow after this incident; your own release policy needs to reject the same source substitution before signing and upload.
For operators, identify litellm==1.107.0 in lockfiles and build records. Also check historical digests for ghcr.io/berriai/litellm, its litellm-database and litellm-non_root variants, and docker.io/litellm/litellm: StepSecurity says v1.107.0 and floating tags pulled between 11:46 and 14:20 UTC on October 21 carried the compromised image. Compare running image digests, since latest, main-latest and main-stable pointed to the affected ghcr.io/berriai/litellm index, sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e, at Socket’s October 21 check. StepSecurity reports those floating tags were subsequently removed or repointed. A tag name seen today cannot tell you which digest a container already ran.
Examine suspect images and wheel archives as data with trusted tooling from a clean environment. Inspect installed site-packages for cook.pth, cook.py and sitecustomize.py; correlate them with Python starts, egress to hxxp://www[.]litellm[.]dev/healthcheck, and the loader’s /tmp/remote_code_loader.lock. The cook.pth SHA-256 in Socket’s report is 7f191632e7320705d154b85204f1ae546b543acbd7e8861229b76f5042b92bdb for one variant. Use the report’s other published hashes when matching additional platforms. A sitecustomize.py filename alone is common and needs a content match. An absent /tmp/.pc_once_72129118c59f5636c0bb marker can follow a failed upload or temporary-file cleanup; use deployment history and network evidence to scope exposure.
Rebuild and verify the release
Stop affected deployments and isolate environments where Python ran after installation. Preserve process, filesystem and network evidence, then rebuild from a reviewed artifact; a package uninstall may leave top-level startup files or a detached loader. StepSecurity identifies 1.106.2 as a reviewed clean release. Pin replacement images by digest, and rotate credentials readable by affected processes from a clean host, including cloud and provider keys, developer sessions and LiteLLM-stored credentials where applicable. For the earlier poisoned-wheel response, see Nulltap’s installation guidance; the separate workflow investigation covers the preceding CI-secret theft.
A release engineer can verify the repaired build by checking that its recorded repository owner and commit match an approved dispatch, then inspecting the exported wheel and image for unexpected top-level .pth and sitecustomize.py files before making the digest available. An operator can verify recovery by matching running digests to those reviewed replacements and confirming the affected startup files are absent from the rebuilt environment. Keep the historical egress and credential-use investigation open for any host that ran the poisoned release: clean replacement bytes cannot undo access already granted to the collector.