I thought deleting the file was enough. I was wrong. Here's what actually happens.
Originally published on Medium — follow me there for more
The Mistake That Haunts Developers
You're coding late at night.
You hardcode your AWS credentials to test something quickly — just this once.
It works. Great.
You delete the credentials from the file. Push to GitHub.
Safe right?
Wrong. Completely wrong. 😰
Your credentials are still on GitHub. Visible to anyone who knows where to look. And automated bots DO know where to look.
This happens to developers every single day. Today I'm going to show you exactly why this happens and how to protect yourself completely.
How Git History Works
Git doesn't just save your current code. Git saves every single version of every file you've ever committed.
Think of git like a time machine. Every commit is a snapshot of your entire project at that moment.
When you delete credentials and push — git saves:
- Commit 1 — file WITH credentials ← still here forever
- Commit 2 — file WITHOUT credentials
Anyone can travel back to Commit 1 and see your credentials. It's that simple.
Let Me Show You Exactly How Easy It Is
If someone wanted to find your deleted credentials they would just run:
# See all commits
git log
# See what changed in a specific commit
git show abc123def
# Search entire git history for keywords
git log -p | grep -i "aws_access_key"
git log -p | grep -i "secret"
git log -p | grep -i "password"
Three commands. Less than 30 seconds. Your "deleted" credentials are right there.
And GitHub makes this even easier — anyone can browse your commit history directly in the browser. No commands needed.
The Bots Are Already Looking
Here's what makes this terrifying.
There are automated bots constantly scanning every public GitHub repository for:
- AWS access keys
- Secret keys
- API tokens
- Passwords
- Private keys
These bots find new commits within seconds of being pushed.
By the time you realize your mistake and delete the credentials — the bots have already found them. Already saved them. Already started using them.
In 2024 a developer pushed AWS credentials to GitHub at 2am. By 4am — $50,000 worth of EC2 instances were running in his account mining cryptocurrency.
Two hours. $50,000.
How to Properly Remove Credentials From Git History
If you've already pushed credentials — deleting them is NOT enough. You need to rewrite git history.
Method 1 — git filter-branch (Built into git)
# Remove a specific file from entire git history
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch path/to/file-with-credentials.py" \
--prune-empty --tag-name-filter cat -- --all
# Force push to GitHub
git push origin --force --all
git push origin --force --tags
Method 2 — BFG Repo Cleaner (Faster and easier)
BFG is a faster alternative to git filter-branch.
# Install BFG
brew install bfg # Mac
# or download bfg.jar from rtyley.github.io/bfg-repo-cleaner/
# Remove all files containing passwords
bfg --delete-files id_{dsa,rsa}
# Replace specific text in all commits
bfg --replace-text passwords.txt
# Clean up
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push origin --force --all
Method 3 — GitHub's Built-in Secret Scanning
GitHub now automatically scans for exposed secrets and notifies you.
Go to your repository → Settings → Security → Secret scanning → Enable
GitHub will alert you if it finds credentials in your code. ✅
The Right Way — Prevent It Before It Happens
Fixing exposed credentials is stressful. Preventing it is easy.
Solution 1 — Use .gitignore Always
Create a .gitignore file in every project:
# .gitignore
# Environment files
.env
.env.local
.env.development
.env.production
# AWS credentials
.aws/credentials
credentials.json
# Key files
*.pem
*.key
id_rsa
id_dsa
Any file listed here will NEVER be committed to git. Ever. ✅
Solution 2 — Use Environment Variables
Never put credentials in your code files. Always use environment variables.
# WRONG ❌ - Never do this
aws_access_key = "AKIAIOSFODNN7EXAMPLE"
aws_secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
# RIGHT ✅ - Always do this
import os
aws_access_key = os.environ.get('AWS_ACCESS_KEY_ID')
aws_secret_key = os.environ.get('AWS_SECRET_ACCESS_KEY')
Set environment variables in terminal:
export AWS_ACCESS_KEY_ID=your_key_here
export AWS_SECRET_ACCESS_KEY=your_secret_here
Or use a .env file with python-dotenv:
pip install python-dotenv
from dotenv import load_dotenv
import os
load_dotenv() # Loads .env file
aws_access_key = os.environ.get('AWS_ACCESS_KEY_ID')
Your .env file:
AWS_ACCESS_KEY_ID=your_key_here
AWS_SECRET_ACCESS_KEY=your_secret_here
AWS_DEFAULT_REGION=ap-south-1
.env is in .gitignore so it never gets pushed. ✅
Solution 3 — git-secrets Pre-Commit Hook
This is the best solution shared by a reader in the comments of my previous article — and it's brilliant.
git-secrets automatically scans your code BEFORE every commit. If it finds credentials — it blocks the commit completely.
# Install git-secrets
brew install git-secrets # Mac
# For Linux
git clone https://github.com/awslabs/git-secrets
cd git-secrets && sudo make install
# Set up in your repository
cd your-project
git secrets --install
git secrets --register-aws
# Now try to commit credentials - it will be blocked!
Once installed — you literally cannot accidentally commit AWS credentials. The commit is blocked before it happens.
This is the cheapest insurance you can get. 🔐
Solution 4 — Use AWS IAM Roles Instead of Access Keys
The ultimate solution — no access keys at all.
When your code runs on EC2, Lambda, or other AWS services — use IAM Roles instead of access keys.
IAM Roles provide temporary credentials automatically. Nothing to hardcode. Nothing to accidentally expose.
# With IAM Role attached to EC2 - no credentials needed at all!
import boto3
# boto3 automatically uses the EC2 instance's IAM Role
s3 = boto3.client('s3')
response = s3.list_buckets()
Zero credentials in code. Zero risk of exposure. ✅
What To Do RIGHT NOW
Go through this checklist immediately:
☐ Search your GitHub repos for "aws_access_key" in commit history
☐ Search for "secret_key" in commit history
☐ Add .gitignore to every project
☐ Move all credentials to environment variables
☐ Install git-secrets on your machine
☐ Enable GitHub secret scanning on your repos
☐ Rotate any credentials that were ever in git history
Even if you think you're safe — check anyway. You might be surprised what you find.
If You Find Exposed Credentials — Do This Immediately
- Deactivate the keys immediately — AWS Console → IAM → Users → Security Credentials → Deactivate
- Create new access keys — fresh keys, stored safely
- Check AWS CloudTrail — see if anyone used your exposed keys
- Check your AWS bill — look for unexpected charges
- Clean git history — use BFG or filter-branch
- Report to AWS — if you see unauthorized usage contact AWS Support immediately
Speed matters here. Every minute counts.
Summary
| Mistake | Reality |
|---|---|
| "I deleted the file" | Credentials still in git history |
| "My repo is private" | Private repos can become public, employees change |
| "Nobody will find it" | Bots scan GitHub 24/7 automatically |
| "It was only for 5 minutes" | Bots find credentials in seconds |
| Solution | Protection level |
|---|---|
| .gitignore | Prevents accidental commits |
| Environment variables | Keeps credentials out of code |
| git-secrets hook | Blocks commits with credentials |
| IAM Roles | Eliminates credentials entirely |
Final Thoughts
This article exists because of a comment from a fellow developer on my previous article about IAM mistakes.
They mentioned git-secrets as "the cheapest insurance" — and they were absolutely right.
The best security lessons come from the community. From real developers who've seen real things go wrong.
If you learned something from this — share it with one developer friend. You might save them from a $50,000 AWS bill. 💪
Follow LearnWithPrashik for more practical AWS security and backend development content.
Connect with me:
LinkedIn: linkedin.com/in/prashik-besekar
GitHub: github.com/prashikBesekar
Top comments (0)