Skip to main content
RunBook Academy

Git, CI/CD & GitOpsFinal · Final AssessmentFinal Review

Incident response and secrets — recap

Advanced⏱ ~28 mingit

What you'll learn

  • Apply the first-respond rule for each of the three incident classes: secret, runner, supply-chain
  • Distinguish revoke-or-rotate from history-rewrite and explain why rotation must precede rewrite
  • Plan a secrets-management model that keeps plaintext secrets out of Git while remaining GitOps-compatible
  • Define a rotation cadence for the credential classes (cloud keys, registry tokens, deploy keys, personal tokens) and the rotation triggers beyond the schedule

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.

CI/CD incidents are not all the same shape, and treating them as the same shape is how teams lose hours to the wrong remediation. The three classes — secret leak, runner compromise, supply-chain compromise — each have a distinct first-respond rule, and confusing them turns a recoverable incident into a multi-day forensic operation.

The three incident classes

flowchart TD
    A[CI/CD incident] --> B{What leaked?}
    B -->|credential| C[Secret leak]
    B -->|code execution| D[Runner compromise]
    B -->|dependency| E[Supply-chain compromise]
    C --> F["First: rotate"]
    D --> G["First: isolate runner"]
    E --> H["First: stop builds"]
    F --> I[Then: rewrite history]
    G --> J[Then: revoke credentials]
    H --> K[Then: identify impact]
  • Secret leak. A credential (cloud key, registry token, personal access token, deploy key) has been exposed — committed to Git, logged in CI output, or shared over an insecure channel. First respond: rotate the credential immediately. The active exposure is the credential, not the Git history. A history rewrite without rotation is a partial fix.
  • Runner compromise. A malicious job, a supply-chain attack via a third-party action, or a vulnerability in the runner host has produced unauthorised code execution. First respond: isolate the runner — drain the queue, remove the runner from the pool, freeze the autoscaler. The active exposure is the runner itself, which can mint new credentials, write to registries, and read every secret in scope.
  • Supply-chain compromise. A dependency, a base image, or a third-party action has been compromised upstream. First respond: stop affected builds. The active exposure is every artifact produced by the compromised component since the compromise began.

The secrets-management model

The operational question is not “how do I store a secret” but “how do I keep plaintext secrets out of Git while remaining GitOps-compatible”. Three patterns, in order of operational complexity:

  • External secret stores. HashiCorp Vault, AWS Secrets Manager, Azure Key Vault. The manifest in Git contains a reference (vault://path/to/secret, aws-secrets-manager://name); a controller in the cluster resolves the reference and mounts the plaintext. The plaintext never appears in Git.
  • Encrypted-in-Git (SOPS, Sealed Secrets). The manifest in Git contains an encrypted blob; a controller in the cluster holds the decryption key and decrypts at apply time. The plaintext never appears in Git, but the encrypted blob is diff-friendly and review-friendly.
  • Plaintext in Git. The manifest in Git contains the plaintext secret. Never acceptable in a production repository — secret scanning will eventually find it, a fork will eventually leak it, and a CI log will eventually expose it.

Rotation cadence and triggers

The two drivers of rotation are time (scheduled) and event (triggered). A rotation policy that has only the time driver is a policy that rotates the credential the day after it leaks. A rotation policy that has only the event driver is a policy that never rotates until something bad happens. The right policy has both:

Credential classScheduled cadenceEvent triggers
Personal access token90 daysDeparture of the owner; team change; suspected exposure
Cloud access keyReplaced by OIDC federationAny leak indicator; IAM policy change
Registry token90 daysDeparture of the owner; CI runner decommission
Deploy key180 daysProject change; suspected exposure
OIDC trust policyReviewed quarterlyOIDC provider change; workflow file rename

Production discipline

The five rules that recur across every incident response:

  1. First respond according to the incident class. Rotate for a secret leak; isolate for a runner compromise; stop builds for a supply-chain compromise. The first action is the one that closes the active exposure; everything else is forensic.
  2. Rotate, do not just revoke. A revoked credential can still be used in caches, in IAM sessions, in role assumptions. Rotation produces a new credential and revokes the old one; revocation alone leaves the active sessions in place.
  3. History rewrite is forensic, not first-respond. The rewrite can happen hours or days later; the rotation has to happen in minutes.
  4. Secrets in plaintext in Git are not a fix. Even with rotation. The secret may not be the only thing in the file, and the next secret will have the same fate. Replace the workflow with a secret-management pattern that does not put plaintext in Git.
  5. A break-glass procedure must be written before the incident. The on-call engineer at 03:00 with a leaked credential does not have time to design a procedure. The break-glass procedure is a runbook entry, not a thought experiment.

Cross-course references

  • Linux for Production Sysadmins — Secret rotation in /etc/shadow, SSH key rotation, and sudo token expiry are the operating-system analogues of CI/CD credential rotation.
  • Kubernetes for Production Sysadmins — The external-secrets operator pattern is the cluster-side resolution of the same problem the CI/CD side faces.

Quiz

Knowledge check · 4 questions

  1. Q1. An engineer accidentally committed a long-lived AWS access key to the main branch six hours ago. The key has `AdministratorAccess`. The team is debating whether to rotate first or rewrite history first. What is the correct order?

  2. Q2. For a runner-compromise incident, the first respond is to isolate the runner (drain the queue, remove from the pool, freeze the autoscaler) before revoking credentials or determining artifact impact.

  3. Q3. Name the three patterns for keeping plaintext secrets out of a GitOps repository and the one that is never acceptable in production.

  4. Q4. A third-party GitHub Action used by the production deploy workflow is discovered to have been compromised upstream. A malicious version was published for 90 minutes before the maintainer reverted it. The deploy workflow ran during the 90-minute window. Walk through the response, in order.

    The Action `thirdparty/setup-terraform` was compromised and a malicious version `v3.0.0` was published. The deploy workflow pinned to `@v3` and therefore pulled `v3.0.0` during the window. The malicious version exfiltrated the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables to an external host. The deploy workflow ran 4 times during the window, against staging, pre-production, and production.

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