Git Notes
Learn about GitHub secret scanning to detect accidentally committed API keys, tokens, and passwords. Configure alerts, push protection, and custom patterns.
It takes just one careless commit to expose an API key to the entire internet. A developer hardcodes an AWS access key during debugging, forgets to remove it, and pushes to a public repository. Within minutes — sometimes seconds — automated bots scraping GitHub detect the key and begin using it to spin up cryptocurrency mining instances. By morning, the AWS bill is thousands of dollars.
This is not a hypothetical scenario. It happens daily. GitHub's secret scanning feature exists to catch these accidents before they cause damage, or to alert you immediately when they slip through.
How Secret Scanning Works
GitHub partners with over 200 service providers (AWS, Google, Stripe, Slack, Azure, and many more) who share the patterns of their credentials. When you push code, GitHub scans the commit content against these known patterns:
When a match is found, GitHub can notify the service provider directly. Many providers will automatically revoke the leaked credential before you even receive the alert.
Enabling Secret Scanning
Navigate to: Settings → Code security and analysis
Push protection is the critical addition. Without it, scanning only alerts you after the secret has already been committed. With push protection, the commit is blocked before it reaches the repository.
Push Protection in Action
When a developer tries to push code containing a detected secret:
git push origin feature/payment-integrationremote: error: GH013: Repository rule violations found for refs/heads/feature/payment-integration remote: remote: ── GITHUB PUSH PROTECTION ────────────────────────────── remote: remote: Resolve the following violations before pushing again remote: remote: ── Push cannot contain secrets ── remote: remote: ╔═══════════════════════════════════════════════════╗ remote: ║ Secret type: Stripe Live API Key ║ remote: ║ Location: src/payment/config.js:23 ║ remote: ║ Secret: sk_live_51Hx... ║ remote: ╚═══════════════════════════════════════════════════╝ remote: remote: To push, remove the secret from your commits. remote: If this is a false positive, you can bypass: remote: https://github.com/org/repo/security/secret-scanning/unblock-secret/...
The push is completely blocked. The developer must remove the secret and rewrite their commits before pushing again.
Responding to Secret Scanning Alerts
When a secret is detected (either in existing history or a new push without protection), follow this response procedure:
Step 1: Revoke Immediately
# The moment you see the alert, revoke the credential
# DO NOT wait until you have removed it from history
# Assume it is already compromisedGo to the service provider's dashboard and invalidate the credential immediately.
Step 2: Remove from Git History
Simply deleting the secret in a new commit is NOT sufficient. The old commit with the secret remains in history:
# Method 1: git-filter-repo (recommended)
pip install git-filter-repo
git filter-repo --invert-paths --path src/config.js
# Method 2: BFG Repo-Cleaner (simpler for secrets)
java -jar bfg.jar --replace-text passwords.txt repo.git
# passwords.txt contains the literal secret values to replace
# Method 3: For a single recent commit
git rebase -i HEAD~3 # Edit the commit containing the secret
# Remove the secret, amend, continue rebase
git push --force-with-leaseStep 3: Generate Replacement Credentials
Create new credentials with the service provider and store them securely (environment variables, secrets manager, not in code).
Step 4: Investigate Exposure
Check the service provider's audit logs for unauthorized usage during the exposure window.
Step 5: Close the Alert
Mark the alert as resolved in GitHub after completing remediation.
Custom Secret Patterns
Organizations can define patterns for internal credentials:
| Settings | Code security → Secret scanning → Custom patterns |
| Pattern name | Internal Service Token |
| Secret format | MYAPP_[A-Za-z0-9]{32} |
| Before secret | (token|key|secret)\s*[:=]\s*["']? |
| After secret | ["']?\s*[,;\n] |
| ✓ matches | token = "MYAPP_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" |
| ✗ ignores | MYAPP_placeholder_for_testing |
Prevention: Stop Secrets Before They Reach Git
.gitignore Fundamentals
# Essential security entries
.env
.env.*
!.env.example
*.pem
*.key
*_rsa
*_ed25519
credentials.json
service-account*.jsonPre-commit Hook with git-secrets
Environment Variables Pattern
// BAD: Hardcoded secret
const apiKey = "sk_live_4eC39HqLyjWDarjtT1zdp7dc";
// GOOD: Environment variable
const apiKey = process.env.STRIPE_API_KEY;
// GOOD: Secrets manager
const apiKey = await secretsManager.getSecret("stripe-api-key");Common Mistakes
Mistake 1: Thinking a new commit that removes the secret is sufficient. Git history retains every version of every file. Use history-rewriting tools to truly remove secrets.
Mistake 2: Not revoking immediately. Developers sometimes want to "investigate" before revoking. Every minute the credential remains active is a window for abuse.
Mistake 3: Bypassing push protection without proper review. GitHub allows bypassing with a reason, but this should require security team approval, not individual developer judgment.
Mistake 4: Only protecting main branch. Secrets in any branch are visible to anyone with repository access. Enable scanning and protection on all branches.
Interview Questions
Q1: What is GitHub secret scanning?
An automated security feature that scans repository content for known credential patterns from 200+ service providers. It detects API keys, tokens, passwords, and connection strings, alerting administrators immediately and optionally blocking pushes containing secrets.
Q2: What is push protection and why is it important?
Push protection blocks commits from being pushed if they contain detected secrets. Without it, scanning only provides after-the-fact alerts — the secret is already exposed in the repository history. Push protection prevents exposure entirely.
Q3: Why is removing a secret in a new commit not sufficient?
Because Git maintains complete history. Anyone with repository access can browse previous commits and find the original secret. The credential must be revoked immediately, and history-rewriting tools must be used to remove it from all commits.
Q4: What should your immediate response be to a secret scanning alert?
Revoke the credential immediately (assume compromise), remove from Git history using filter-repo or BFG, generate a replacement credential, investigate potential unauthorized usage during the exposure window, and close the alert after remediation.
Q5: How do you prevent secrets from being committed in the first place?
Use multiple layers: .gitignore for secret files, pre-commit hooks (git-secrets) scanning for patterns, environment variables instead of hardcoded values, secrets management tools (Vault, AWS Secrets Manager), enable push protection, and team education about secure coding.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Secret Scanning - Detect Leaked Credentials in Code.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Git & GitHub topic.
Search Terms
git-github, git & github, git, github, security, secret, scanning, secret scanning - detect leaked credentials in code
Related Git & GitHub Topics