Someone with push access to LiteLLM’s GitHub repository ran a secret-stealing workflow on October 10, eleven days before the compromised litellm==1.107.0 release. Socket’s newly recovered commits and GitHub records put the first successful Actions run on a temporary branch, followed by a broader run on October 12. Teams investigating the October 21 poisoned PyPI wheels and Docker images now have an earlier window for organization and CI credentials.
The October 10 workflow named six organization secrets, including GH_TOKEN and a GitHub App private key. The October 12 version reached five GitHub Environments and named 14 more distinct secrets, among them provider API keys, database passwords and browser session state. Socket calls it “a compromise window of at least eleven days.” Rotate credentials available to those runs: the workflows suppressed delivery errors, so a successful job marks execution while leaving delivery uncertain.
Temporary branches reached live secrets
Socket recovered two unsigned commits adding .github/workflows/cache.yml. The October 10 commit, b69bc36fd4e23b23ea09f4ce63a92b07258f5044, went onto ci-tmp-a351cc; the October 12 commit, 1a6e3c1e41f1b5c8eeaeeb2ae94bcd95390fa891, went onto ci-tmp-4d8517. Both used the subject ci: bump cache config, created a new workflow file, ran and left behind deleted branches. Each workflow was triggered by a push in the upstream BerriAI/litellm repository, where Actions could resolve secrets.* values. The push context exposed upstream repository secrets to the jobs.
The first file defined one job. It put six secret values into a temporary file, base64-encoded the contents and posted them to a webhook.site collector controlled through an attacker-selected endpoint. The October 12 file defined six jobs. Its organization job reached repository and organization secrets; five other jobs bound the real environments e2e-changed, integration-postgres, integration-providers, integration-redis and integration-redis-postgres to reach their scoped secrets. The second run used a different collector endpoint and per-job X-Tag values. Both files ended the send step with || true.
The October 10 targets included LINEAR_API_KEY, LITELLM_API_KEY, TOGETHER_API_KEY, PROVIDER_INFO_SYNC_APP_ID and PROVIDER_INFO_SYNC_APP_PRIVATE_KEY alongside GH_TOKEN. The second run reached OPENAI_API_KEY, ANTHROPIC_API_KEY, AWS_BEARER_TOKEN_BEDROCK and GITGUARDIAN_API_KEY, plus environment-scoped DATABASE_URL, POSTGRES_PASSWORD, REDIS_PASSWORD and E2E_LINEAR_STORAGE_STATE_B64. That last name denotes Playwright browser session state for Linear. A still-valid session can grant access even after its user’s password changes, so revoke the session as well as rotating API keys.
Deleted branches left deployment records
Socket matched the commits to repository activity, Actions performance metrics and GitHub Environment deployment history. The metrics recorded one successful cache.yml run on October 10 with one job, then another on October 12. The latter workflow’s jobs bound environments, which created deployment entries that persisted after the branch disappeared. Socket found the integration-redis deployment from ci-tmp-4d8517 still marked Active under the commit subject ci: bump cache config. Searching only the current default branch for .github/workflows/cache.yml would miss the temporary workflow.
The repository activity log attributes branch creation, pushes and deletion to the authenticated account ishaan-berri. Use the organization audit log to investigate the account’s sessions, token or SSH-key use, source addresses and changes around October 10; the account name identifies the principal used for those operations, not the person operating it. Socket says it contacted LiteLLM and coordinated publication. It also reports that LiteLLM’s subsequent investigation traced initial access to an Agent Platform master key committed publicly in May and says a GH_TOKEN taken in the October 10 workflow was later used to approve the malicious release.
Scope the release separately
The October 21 artifact investigation by StepSecurity found the credential stealer in all seven 1.107.0 PyPI wheels and in affected official Docker images. Those package and container exposures demand host recovery and rotation of credentials accessible from installed systems, as Nulltap covered at release time. The earlier Actions runs add repository, organization and environment secret scopes to the incident response. CI secret owners need credential rotation alongside the host recovery for poisoned installs.
Preserve runs and replace exposed credentials
For a LiteLLM organization or a team sharing credentials with its CI, export Actions runs, repository activity and environment deployment history for October 10 through October 21 before retention or cleanup removes them. Search for the two ci-tmp- refs, the cache.yml workflow, both commit hashes and deployments titled ci: bump cache config. In retained runner and outbound HTTP telemetry, look for /tmp/c.env, /tmp/c.b64, X-Tag: lm1 or the October 12 tags org, e2e, intpg, intprov, intredis and intrp. The two observed collector URLs are https://webhook.site/65a42464-3cfa-4b02-a18c-17a6d7b86f37 and https://webhook.site/4da03473-a3e7-4dc2-a087-9c564b4208e1. webhook.site is a legitimate shared service abused here through those endpoint IDs; match the full URLs rather than blocking the entire service on this case alone.
Revoke the implicated GitHub user tokens and App key, issue new provider and database credentials from a trusted environment, and invalidate the Linear session state where it was present. Recheck which secrets each environment made available to the October 12 jobs before restoring its workflows. Compare the exported run and deployment records with the new credential inventory: the October 10 single-job run and October 12 environment deployments should be accounted for, and the old credentials should fail an authentication check. Use the archived run and deployment records for this comparison after branch cleanup.