
The LiteLLM breach showed how a single force-push to a Git tag can expose your CI secrets. SHA pinning closes the door in two hours.
In March 2026, LiteLLM got breached through a poisoned Trivy GitHub Action. The attacker didn't publish a new malicious action under a typo-squatted name. They force-pushed malicious code to existing release tags teams were already using.
That @v1 or @v2 you pinned to? It's mutable. Anyone with write access to that repo can point it at completely different code whenever they want. No diff. No notification. No PR review.
Here's what most workflows look like:
uses: actions/checkout@v1
That @v1 feels pinned. It looks like a version. Your brain pattern-matches it to npm semver or Docker tags and moves on. Git tags are not immutable. A maintainer, or an attacker who has compromised a maintainer, could delete and recreate that tag pointing at any commit they want. Your next workflow run pulls the new code silently.
Tag pinning gives the illusion of reproducibility without actual reproducibility. You're trusting every maintainer of every action, forever, with access to your CI secrets. A single compromised token upstream means your GITHUB_TOKEN, cloud credentials, and deploy keys are exposed.
Every startup I've worked at has pinned to tags. Every template repo on GitHub has pinned to tags. Every getting-started tutorial has told you to pin to a tag. We all collectively normalized this.
GitHub themselves recommend pinning actions to full commit SHAs:
uses: actions/checkout@a1b2c3d4e5f6... # v2.1.0
A commit SHA is immutable. You can't force-push over it. If someone pushes malicious code, it gets a new SHA, and your workflow will keep running the old, safe commit. SHA pinning is the only pinning that actually pins anything. Tools like Dependabot and Renovate can auto-update SHA pins with readable diffs. You can add a comment with the tag for readability.
Yes, it's ugly. Yes, it's annoying. Annoying beats compromised every single time.
We dedicated years to studying left-pad, event-stream, and colors.js. We created lockfiles, SBOMs, and signed packages. Then we turned around and gave our CI pipelines, the things with write access to production, zero supply chain discipline.
Your CI runner has secrets that your application code doesn't. Cloud provider keys. Package registry tokens. Deploy credentials. For most organizations, it's the single highest-value target, and we're protecting it with vibes.
The LiteLLM incident wasn't sophisticated. It was embarrassingly simple, and that's what makes it terrifying.
After reading about this, I spent an afternoon auditing our workflows at the startup where I work. Every single third-party action was pinned to a tag. Every one. I replaced all of those with SHA pins plus tag comments, and added Renovate to automatically open PRs with the new SHAs. The whole thing took maybe two hours. Two hours to close a door that was wide open to any upstream compromise.
If you haven't done this yet, maybe today's the day.
Drafted by a large language model from the source reporting linked above, then screened by automated publishing checks. It is not read by a journalist before publication. Some articles cite our Alpha Score. Verify prices and figures against the original source. Educational coverage, not personalized advice.