This is part seven of Ship the Proof. The earlier parts built a chain of verifiable claims. This part is why that chain is not optional. Three hazards became concrete in 2026, and each one has a single underlying lesson: a mutable reference in your trust path is a liability, and verifying once is not the same as verifying everywhere.

For a long time “supply-chain security” was an abstraction you nodded at in a threat model and then ignored. In March 2026 it stopped being abstract. The tool a lot of teams use to scan their images for vulnerabilities was turned into a credential thief, and it happened through a mechanism every pipeline relies on without thinking: the mutable git tag.

The scanner itself got compromised

The Trivy ecosystem was compromised, tracked as CVE-2026-33634 and GHSA-69fq-xp46-6x23. The advisory is blunt about the scope: in trivy-action, “76 of 77 version tags force-pushed to malicious commits,” and in setup-trivy, “all 7 existing tags (v0.2.0 to v0.2.6) were force-pushed to malicious commits.” The payload “dumps Runner.Worker process memory via /proc/<pid>/mem to extract secrets” and “sweeps 50+ filesystem paths for SSH keys, AWS/GCP/Azure credentials, Kubernetes tokens, Docker configs, .env files, database credentials” (GHSA-69fq-xp46-6x23).

Sit with the shape of this. The thing scanning your images for compromise was the compromise. Every secret your runner could see (cloud credentials, cluster tokens, signing keys) was in scope. The safe versions, per the advisory, are Trivy v0.69.2 or v0.69.3, trivy-action v0.35.0, and setup-trivy v0.2.6. That is the patch. The lesson is bigger than the patch.

The actual bug was trusting a mutable reference

It is tempting to file this under “Trivy got hacked, glad I do not use it.” That misses the point. The attack worked because workflows referenced tags, and a force-push silently re-pointed those tags at malicious commits. Nothing in the referencing workflow changed. The next run just pulled different code. Any dependency you reference by a mutable name is exposed to exactly this.

The fix is to pin to immutable identity, and the form depends on what you are pinning. A GitHub Action is a git reference with no content digest, so pin it by full commit SHA, which cannot be force-pushed out from under you because it is the content. A container image or a tool delivered as an OCI artifact gets pinned by its sha256: content digest.

# Not this: the tag can be re-pointed at attacker code
- uses: some-org/some-action@v4
# This: the commit is immutable
- uses: some-org/some-action@e3dd6a429d7300a6a4c196c26e071d42e0343502

“Pin by digest” is shorthand for “pin to whichever immutable identity the artifact type provides.” For actions that is the commit SHA. For images it is the content digest, the same identity the first part of this series argued is the release itself. Both remove the mutable name from the trust path, which is the only thing that made the March attack possible. Yes, it makes upgrades a deliberate, reviewed step instead of a silent background slide. That is the feature, not the cost.

Keyless signing changed shape under you

If you sign artifacts keyless, the transparency log you write to changed in late 2025, and pipelines that assumed the old behavior break. Rekor v2 reached general availability on 10 October 2025. The new log will “periodically rotate the log instance,” freezing the previous instance shortly after. It supports only two entry types now (the hashedrekord and dsse types), “the search index has been removed,” and “the log no longer returns signed timestamps with proofs,” which clients now fetch from a dedicated service (Rekor v2 GA).

Three operational consequences fall out of that, and none of them are optional once you depend on the log:

  • Your client has to be current. The announcement states support for Rekor v2 “upload and verification” arrived in cosign v2.6.0. Require cosign 2.6.0 or newer; older clients cannot transact with the new log at all.
  • Rotation is periodic, not annual. The source says “periodically,” and the previous instance is frozen shortly after a new one starts. Verification has to tolerate entries living in a frozen prior shard. Do not hard-code an assumption that rotation happens once a year on a known date. Build re-anchoring into routine tooling maintenance.
  • Stop depending on the removed search index. Reference entries by their own identifiers. Anything that searched the log to find an entry is broken.

Promotion still orphans attestations if you let it

The third hazard is the one an earlier part of this series covered in full, so the short version here is a reminder, not a repeat. Attestations attach to an image as separate OCI referrer manifests, not as image layers. A naive image-only copy by digest moves the image and leaves the signatures, the bill of materials, and the provenance behind in the source registry. The fail-closed gate at the next boundary then correctly rejects an image whose evidence has vanished. The defense is a referrer-aware copy followed by verification at the destination. Copying the image is not the same as copying its attestation graph.

One lesson under three incidents

Read the three together and the same sentence falls out of all of them. A mutable reference in your trust path is a liability: the tag that got force-pushed, the client that assumed a log shape that changed, the copy that moved an image but not its evidence. The defenses rhyme. Pin to immutable identity. Keep the clients that verify your claims current. Verify the attestation graph at every boundary, not just the first one. Trust the digest, verify the graph, and keep the things that do the verifying up to date. None of that is exotic, and 2026 made clear it is not optional.

The next part turns from defending the pipeline to measuring it honestly, starting with a word everyone reports on and almost nobody defines: a deployment.

Sources