Skip to main content
If you committed a credential and then removed it in a later commit, it is still exposed. Anyone who has cloned the repository can read it from git history. Rotation is mandatory.
This guide covers what to do when BattleTest flags a committed secret, or when you discover one yourself. The steps apply to any credential: AWS access keys, API tokens, database passwords, private keys, or service account credentials.

Step 1: Rotate the credential immediately

Before anything else, revoke the exposed credential and issue a new one. Do this now, before touching git history — if the key has been in a public or shared repository, assume it has already been read. After rotation, update the new credential in your deployment secrets manager (environment variables, Vault, AWS Secrets Manager, etc.) — not in code.

Step 2: Remove the credential from current code

If the credential is still in your codebase (not just in history), remove it:
  1. Find all occurrences: grep -r "AKIAIOSFODNN7EXAMPLE" . (use your actual key prefix)
  2. Replace with an environment variable reference: process.env.AWS_ACCESS_KEY_ID
  3. Add the secret to your secrets manager or .env file (not committed)
  4. Add .env to .gitignore if it isn’t already
Commit the removal.

Step 3: Purge the credential from git history

Removing a secret from current code doesn’t remove it from git history. You need to rewrite history. Option A: git filter-repo (recommended)
Option B: BFG Repo Cleaner (faster for large repos)
Both tools rewrite every commit in your history that contained the secret.

Step 4: Force-push to the remote

After rewriting history locally, push the rewritten history to the remote:
Force-pushing rewrites the shared history for everyone who has cloned the repository. Anyone with a local clone will need to re-clone or run git fetch --all && git reset --hard origin/main.
If this is an organisation repository with branch protection rules preventing force-push, you’ll need to temporarily disable protection rules or coordinate with an admin.

Step 5: Notify anyone who has access to the repository

If the repository is or was public, or if it’s a shared private repository, assume the credential has been seen. Notify your team that they need to re-clone and that the old credential is revoked. If the key had write or admin access to a production system, check your audit logs for unexpected activity during the period the key was exposed.

Step 6: Prevent recurrence

BattleTest’s secret scanning runs against the full commit history of every PR branch — not just the diff — so it catches secrets that were committed and then “removed” before the PR was opened. To avoid future incidents:
  • Use environment variables. Never hardcode credentials, even in config files committed to a private repo.
  • Add pre-commit hooks. Tools like detect-secrets or gitleaks can prevent secrets from being committed in the first place.
  • Connect BattleTest to your repositories. Every PR gets scanned automatically. See Get your first PR security review.
BattleTest scans the full commit history of every PR branch, not just the diff — so a secret that was committed and later “removed” is still caught. For how secret scanning works, see How PR review works. To dismiss a secret found in a test fixture, see How to review, dismiss, and track findings.