Recover a secret that was committed and pushed

applied · 40 min · Objective 4.4

Task

Commit a secret to a repository, push it, and then carry out the correct remediation -- which is not "delete it in the next commit". This is the incident every team meets, and getting the order right matters: rotate first, clean history second, and understand why the deletion commit achieves nothing.

Steps

  1. Commit an application config containing an API key, and push it to the "remote". Confirm it is there with git log -p.
  2. Make the naive fix: remove the key in a new commit and push. Then prove it did nothing for the exposure -- the key is still in the earlier commit, and git log -p and git show <first-hash> both still contain it.
  3. State the order of correct remediation before doing it: the key is disclosed the moment it is pushed, so ROTATE it first. Simulate rotation by generating a new key and updating the config.
  4. Clean the history: use git filter-repo (or the older filter-branch/BFG) to remove the file from every commit. Confirm the key no longer appears anywhere in git log -p.
  5. Force-push the rewritten history and explain, in one sentence, why every other clone is now inconsistent and must re-clone.
  6. Prevent a recurrence: add a pre-commit hook or gitleaks that refuses to commit a file matching a secret pattern, and prove it blocks a new attempt.
  7. Add the secret's path to .gitignore and confirm a fresh secret file is no longer even a candidate for committing.

Verify

cd ~/lab-secret/work
git log -p | grep -c 'API_KEY_VALUE'          # non-zero before cleaning
# after filter-repo:
git log -p | grep -c 'API_KEY_VALUE'          # 0
git log --all --oneline | wc -l               # history rewritten
echo 'API_KEY_VALUE=x' > new.env && git add new.env 2>&1 | grep -qi 'secret\|blocked' && echo "hook blocks secrets"

The count going from non-zero to zero across filter-repo is the history clean. But the lab's real lesson is the order: by the time you are cleaning history the key has already been disclosed, so rotation in step 3 is the actual remediation and everything else is tidying up after it.

Notes

"Removing a secret from the latest commit" is the reflex to unlearn. The secret is in every earlier commit and in every clone anybody has taken; the deletion commit only stops it being in the tip. A pushed key is a disclosed key -- rotate it, then clean up.