Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXXXIII · Commit and Tag SigningSigningFoundations

Why sign commits — the chain of trust and what signing actually proves

Advanced⏱ ~22 mingit

What you'll learn

  • Explain what a cryptographic signature on a commit or tag extends over an unsigned one
  • Distinguish identity assertion from intent, review, and code quality
  • Map the chain of trust from commit hash to a key fingerprint to a real-world identity
  • Identify the failure modes that signing does not prevent

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.

Signing commits and tags extends the chain of trust from the commit hash to a cryptographic identity. An unsigned commit proves only that somebody made the change; a signed commit proves that the holder of this private key made the change.

What a signature extends

An unsigned commit carries three pieces of identity metadata: author name, author email, committer name and email. Every one is a string the engineer typed — there is no cryptographic proof that “Alice” is the same Alice with access to the production repository. A signed commit adds a signature over the commit bytes, produced by a private key whose public half can be looked up in a trust store.

flowchart LR
    A["unsigned commit\nself-asserted"] --> B["signed commit\nsignature + fingerprint"]
    B --> C["verifier checks signature"]
    C --> D["valid + trusted?"]
    D --> E["out-of-band check"]

The verifier’s job is to check that the signature is mathematically valid and that the key fingerprint matches an entry in the trust store. The out-of-band check — publishing the fingerprint through a channel independent of Git — is where the chain of trust becomes a chain of identity. A valid signature by an unknown fingerprint is operationally meaningless.

What signing proves, and what it does not

A signature proves four things and only four: identity at a moment (the keyholder made the commit at this timestamp), integrity (the bytes have not been altered), non- repudiation within the key’s lifetime (the signer cannot credibly deny without claiming compromise), and verifiability by anyone with the public key. It does not prove: that the code is correct, that the commit was reviewed, that the keyholder is trustworthy, or that the key has not been stolen. Cryptographic verification cannot distinguish a legitimate signer from an attacker holding the same private key — key custody is operational, not cryptographic.

The chain of trust

flowchart LR
    A["commit bytes"] --> B["signature"] --> C["key fingerprint"]
    C --> D["trust store entry"] --> E["out-of-band identity"]
    E --> F["trustworthy commit"]

The first two links are cryptographic (git verify-commit, git log --show-signature). The third is lookup against a trust store (GPG keyring or allowedSignersFile). The fourth is publication of the fingerprint through a channel independent of the repository. The fifth is operational policy: the fingerprint belongs to an authorised person on the team today, and the key has not been reported compromised. A break at any link invalidates everything downstream.

Failure modes signing does not prevent

A compromised laptop produces valid signatures (the attacker is the signer). A coerced signer produces valid signatures under duress. A signed merge of unreviewed code carries a signature on the merge, not on the review. A signed tag pointing at an unsigned commit chain is valid for the tag but unattested for the contents. A signed commit by an off-boarded employee is valid until the trust store is updated. Each is an operational failure requiring operational remediation: key rotation, dual-control ceremonies, branch protection, CI ancestry verification, and a joiners-movers-leavers process that touches the trust store on the day of offboarding.

Production discipline

  1. Document the trust model. State which keys are trusted, how fingerprints are published, who maintains the trust store.
  2. Layer signing with other controls. Branch protection defends review; CI defends correctness; signing defends identity.
  3. Audit the trust store on joiners-movers-leavers cadence. Stale trust stores are a chain-of-trust break.
  4. Revoke keys the moment they are suspect. Laptop theft, offboarding, suspicious activity.

Cross-course references

  • Git, CI/CD & GitOps — Part XXVI-06 (Signing configuration) — the settings that turn cryptography into a default behaviour.
  • Git, CI/CD & GitOps — Part XXXII (Protected branches) — branch-protection rules that require signed commits.
  • Linux for Production Sysadmins — Part XII (RepositorySecurity) — apt/dnf repository signing, where the same chain applies at the OS-package level.

Quiz

Knowledge check · 4 questions

  1. Q1. An attacker steals an engineer's laptop containing an unencrypted SSH signing key. The attacker commits, signed with the stolen key. The forge shows 'Verified'. What does the badge actually attest?

  2. Q2. A signed commit proves the commit was produced by a trusted person.

  3. Q3. Name three things a commit signature proves and three things it does not prove.

  4. Q4. Diagnose an audit where signed commits were accepted as proof of trust, and identify the chain-of-trust link that broke.

    Three months after a contractor leaves, a commit signed by the contractor's SSH key appears in production. The signature is valid; the forge shows 'Verified'; CI passes. Six weeks later an incident traces to a backdoor in the change. The audit team proposes disabling signing.

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