Skip to content

Rotate a compromised GPG key

Remove a compromised private key from every vault it could read and rotate the underlying secrets at their source. Applies whether the compromised key is yours or a teammate’s.

  1. Generate or import a replacement identity. If the compromised key is yours, generate a new pair (gpg --full-generate-key), publish the new public key, and have each teammate import it.

  2. Revoke the compromised fingerprint from every affected secret. secret revoke takes one secret name per call, so loop over the key list that secret get (no arguments) prints.

    Terminal window
    for s in $(dotsecenv secret get); do
    dotsecenv secret revoke "$s" <COMPROMISED_FP> --all
    done
  3. Add the replacement recipient.

    Terminal window
    dotsecenv secret share <SECRET_NAME> <NEW_FP> --all
  4. Rotate each affected secret at its source. Generate a new credential at the originating system (database, IDP, cloud provider, API issuer) and store it. This is what neutralizes the compromise.

    Terminal window
    echo "<new-value>" | dotsecenv secret store <SECRET_NAME>
  5. Verify. Every current secret should list the new key as a recipient and not the compromised one.

    Terminal window
    dotsecenv vault doctor
    dotsecenv vault describe
  6. Commit.

    Terminal window
    git add path/to/vault
    git commit -m "Rotate compromised key <COMPROMISED_FP>, rotate N secrets"

Blast radius: repo-scoped vs org-wide keys

Section titled “Blast radius: repo-scoped vs org-wide keys”

The scope of the compromised key sets the scope of the rotation. A repo-scoped CI key (GPG_PRIVATE_KEY) only decrypts one repository’s vault, so revoke, re-share, and source-rotate stay contained to that repo. An org-wide key (ORG_GPG_PRIVATE_KEY) decrypts every vault that listed it as a recipient, so you must run the runbook against each affected repo: revoke the fingerprint, share the replacement, rotate the secret at its source, and commit in every one. Track the full list before you start so none are missed. See Key Scope for the trade-offs.

  • Erase a leaked entry from the vault file. Append-only by design. Rewriting git history with git filter-repo is possible, but anyone who already cloned the repo still has the old data and the compromised key still decrypts it.
  • Re-encrypt an existing entry to a different recipient set. secret share and secret revoke only affect future writes. Source rotation is the only fix.