The one-sentence version
Committing API keys, database passwords, or private keys into code repositories is one of the most common and easily avoidable security incidents. Once pushed to a public repository, automated scanning bots will often find and exploit them within minutes. Even worse, Git remembers everything: even if you delete the file and commit again, the key still lies within the history. There are three layers of defense: intercepting with hooks before committing, platform interception during pushing, and continuous scanning after the fact. Once a leak occurs, the only reliable remedy is to immediately rotate the keys.
This article has three layers:
- Layer 1: The Intuition: Leaving your keys on a public bulletin board
- Layer 2: Real-World Use: Uber and Toyota incidents, GitHub push protection
- Layer 3: Principles and engineering key points: How to identify keys, the three lines of defense, and post-leak procedures
Layer 1: The Intuition
1.1 Leaving your keys on a public bulletin board
You post a photo of your house keys on a public bulletin board in your residential community, realize your mistake a few minutes later, and quickly tear it down.
However:
- Someone has already taken a photo;
- The bulletin board has a "history" feature, allowing anyone to view the version before you tore it down.
At this point, the only solution is to change the locks. A public Git repository is exactly like this bulletin board.
1.2 Why people keep making this mistake
- Writing them temporarily in the code for debugging and forgetting to remove them;
- Committing
.envfiles (failing to add them to.gitignore); - Changing a private repository to public without realizing there are keys in the history;
- AI programming tools hardcoding keys to make the code run (see "Credential Leaks and Context Windows").
Layer 2: Real-World Use
- Uber (2016): An attacker gained access to a private code repository used by Uber engineers, found AWS access keys, and subsequently downloaded data for approximately 57 million users and drivers from cloud storage. Uber also paid the attacker $100,000 to keep the incident quiet, which later resulted in regulatory penalties and the indictment of their former Chief Security Officer.
- Toyota (2022): A contractor accidentally published source code containing access keys to a public repository; it was discovered nearly five years later, potentially involving approximately 300,000 customer email records.
- Automated Exploitation: Multiple security studies have placed "decoy" cloud keys in public repositories and observed that they are typically attempted for use within minutes to hours.
- GitHub Push Protection: GitHub partners with many service providers to identify hundreds of key formats; starting in 2024, push protection is enabled by default for public repositories. If a push contains a key in a known format, it will be directly blocked. Many service providers automatically revoke the key upon receiving a leak notification from GitHub.
Layer 3: Principles and Engineering
3.1 How to identify keys
| Method | Description |
|---|---|
| Fixed Format | Many services have fixed prefixes and lengths. For example, AWS access keys start with AKIA, GitHub tokens start with ghp_, and private key files start with -----BEGIN ... PRIVATE KEY-----. High accuracy. |
| High-Entropy Strings | A long string that looks random might be a key. High false positive rate. |
| Context | Assignments where variable names are password, secret, or token. |
| Validation | Some tools attempt to call the service provider's API using the discovered key to confirm if it is still valid, helping to prioritize response. |
Service providers design prefixed key formats specifically to make scanning more accurate.
3.2 Three lines of defense
| Defense | Tool | Role |
|---|---|---|
| Before Committing | gitleaks, detect-secrets, etc., used as pre-commit hooks | Intercepts locally so the key never enters the history. |
| During Pushing | Push protection on code hosting platforms | Intercepts even if no local hooks are installed. |
| After the Fact | Platform secret scanning, trufflehog, etc., scanning the entire history | Detects leaks that have already occurred. |
Combined with source-level measures:
.gitignorecontains.env, key files, and cloud credential directories;- Use keystores or secret management tools for local development instead of plaintext files (see "Least Privilege and Key Management");
- Never put any secrets in frontend code; frontend code is visible to everyone.
3.3 Post-leak response workflow
Key points:
- Rotation is the first step, and the only reliable step. Deleting commits, rewriting history, or making the repository private is not enough: the key may have already been copied, and it may still exist in forks, caches, or mirrors;
- Rewriting Git history (e.g., using
git filter-repo) can reduce the chance of it being discovered again in the future, but only after it has been rotated; - Check the service provider's access logs to see if there were any anomalous calls within the leak window;
- Conduct a post-mortem and patch the missing defenses (see "Incident Response and Post-mortems").
3.4 Minimizing the impact of a leak
Even with best practices, leaks can happen. Preparing these in advance can significantly reduce the impact:
- Keys should have least privilege and short expiration (see "Least Privilege and Key Management");
- Set usage limits and budget alerts on cloud services (see "Rate Limiting and Abuse Prevention");
- Use keyless solutions like OIDC whenever possible instead of long-lived keys (see "CI/CD Pipeline Security").
Summary
| Layer | Key points |
|---|---|
| Risk | Keys in public repositories can be exploited within minutes; Git history remembers everything |
| Identification | Fixed prefix formats are most accurate; high entropy and context serve as supplements |
| Defense | Pre-commit hooks, push protection, post-event scanning |
| Post-leak | Immediate rotation; deleting records is insufficient; check logs; post-mortem |