Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXCV · Incident: Compromised RunnerIncidentResponse

Invalidate and rebuild — the rebuild from clean source, on a clean runner

Advanced⏱ ~28 mingitkubectlcosign

What you'll learn

  • Sequence the rebuild: invalidate, re-trigger from clean commits, build on a clean runner, re-sign, re-deploy
  • Apply the three verification gates: clean runner, clean commit, clean signing key
  • Distinguish a re-build (same source, new runner) from a re-release (new source) and pick the right one for each artifact class
  • Document the rebuild with manifest diff, signing-key identifier, and verification gates that survive the audit

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

Invalidation is the warning. The rebuild is the fix. A team that invalidates the compromised artifacts but does not rebuild and re-deploy leaves production running on the bytes the attacker may have tampered with. The rebuild runs on a clean runner, from a clean commit, with a clean signing key. The three verification gates prove the rebuilt artifact is not the same bytes the attacker produced.

The rebuild sequence

The sequence is forced by the supply-chain constraint that every step must be reproducible from a trusted input:

flowchart LR
    A["invalidated artifacts"] --> B["re-trigger from clean commits"]
    B --> C["build on clean runner"]
    C --> D["re-sign with new key"]
    D --> E["deploy with admission control"]
    E --> F["verify three gates passed"]
  • Re-trigger from clean commits. The workflow is re-run, but not on the compromised runner. The commit hash must be the same as the original (or a newer-known-good commit), not a re-push of the same source.
  • Build on a clean runner. A fresh runner that has never run a job for this workflow, with no persistent state from the compromised runner.
  • Re-sign with a new key. The signing key the runner used is in the credential inventory and must be rotated. The new key signs the rebuilt artifact; the old signature is meaningless.
  • Deploy with admission control. The cluster’s image admission policy rejects the invalidated artifacts and accepts the new signed ones.
  • Verify three gates passed. Clean runner, clean commit, clean signing key — all three are recorded in the rebuild log.

The three verification gates

Each gate answers a question about a different link in the supply chain:

GateQuestionEvidence
Clean runnerWas the artifact built on a runner the attacker never touched?Runner registration time after the runner pool was rebuilt
Clean commitIs the source the same commit the original was built from?Git commit hash signed by the build runner
Clean signing keyWas the signature made by a key the attacker never held?Key rotation timestamp before the rebuild

Re-build versus re-release

The team chooses between two operations for each artifact:

  • Re-build. The source is the same commit the original was built from. The bytes may differ because the build environment is different, but the source is byte-identical. This is the default for container images and build artifacts.
  • Re-release. The source is a newer-known-good commit that contains a security fix or a dependency update. The bytes will differ intentionally. This is the right choice when the original source contained a vulnerability the attacker exploited.

A re-release requires a code change, a pull request, a review, and a merge. A re-build requires a clean runner and a re-trigger. The audit log distinguishes the two by recording whether the commit hash changed.

The signing key rotation

The signing key the runner used to sign attestations is in the credential inventory from lesson 03. The rotation follows the disable-rotate-revoke sequence:

# Disable the old cosign key
cosign import-key --key old-key.pub

# Generate a new cosign keypair
cosign generate-key-pair

# Sign the rebuilt artifact with the new key
cosign sign --key new-key.pem "$IMAGE_REFERENCE"

The new key is stored in the secret manager with a key rotation timestamp that survives the audit. The old key is revoked in the cosign key transparency log.

Deploying with admission control

The rebuilt artifact is deployed through the cluster’s image admission policy. The policy rejects the invalidated artifacts by digest and accepts the new signed ones:

apiVersion: security.k8s.io/v1
kind: ImagePolicyWebhook
metadata:
  name: production-image-policy
webhook:
  imagePolicy:
    allowWhenInsecure: false
    allowedRegistries:
      - production-registry.example.com

The admission policy is the gate that prevents the invalidated artifacts from being re-pulled by any consumer that did not receive the invalidation notification.

Production discipline

  1. Three gates, not one. A single gate is not a rebuild.
  2. Re-build by default; re-release when source changed. The decision is logged with a reason.
  3. Signing key rotation before rebuild. The new signature must be made by a key the attacker never held.
  4. Admission policy is the deploy gate. The policy rejects the invalidated digests.

Cross-course references

  • Linux for Production Sysadmins - Part XXXII (ContainerImages) covers the registry-side validation patterns the rebuild relies on.
  • Kubernetes for Production Sysadmins - Part XXIII (ImageSupplyChain) covers the admission policy patterns the deploy gate enforces.
  • Terraform for Production Sysadmins - Part XV (CredentialRotation) covers the rotation patterns that apply to the cosign signing key.

Quiz

Knowledge check · 4 questions

  1. Q1. A rebuild is being planned for a compromised container image. The signing key the runner used is in the credential inventory. When must the signing key be rotated?

  2. Q2. A rebuild that runs on a re-imaged runner from the same commit, signed with the rotated key, passes all three verification gates.

  3. Q3. Name the three verification gates the rebuild must pass and state what each gate answers.

  4. Q4. A production container image has been invalidated. The rebuild plan runs on a fresh Kubernetes runner pod, from the same commit hash, signed with the rotated cosign key. Walk through the gates and identify what is missing.

    The runner pool was rebuilt at 09:00. The new runner pod is registered at 09:14. The workflow re-runs at 09:16 from commit a3f9d2c. The cosign key was rotated at 08:45 and the new keypair is stored in the secret manager. The image is pushed at 09:23 and signed at 09:24.

Passing score: 75%. Answers are checked in this browser.