How to Find and Fix Hardcoded Secrets in Your Codebase
Hardcoded secrets are the leading cause of data breaches. Here is a comprehensive guide to identifying, removing, and preventing exposed API keys in your repository.
Hardcoding secrets—API keys, database credentials, JWT signing keys, and cloud provider tokens—is one of the most dangerous and common security mistakes a developer can make. Once a secret is committed to a repository, it is considered compromised, even if the repository is private.
In this guide, we will explore why hardcoded secrets happen, how to find them in your existing codebase, and the steps required to permanently fix the issue.
Why Do Secrets End Up in Code?
Most hardcoded secrets start innocently enough. You are testing a new API integration, you paste the key directly into your fetch function to "just see if it works," and you promise yourself you'll move it to an environment variable later. Fast forward three days, you commit the feature, and the key goes with it.
With the rise of AI coding assistants, this problem has multiplied. AIs often generate code with placeholder strings like "sk_live_12345", and tired developers sometimes replace them with real keys directly in the file.
How to Find Hardcoded Secrets
Finding secrets manually in a large codebase is nearly impossible. Attackers use automated tools to scan public repositories for key patterns within seconds of a commit. You need to use similar tools to protect yourself.
sk_live_, and AWS Access Keys typically start with AKIA. You can use tools like grep to search your codebase for these patterns.git-secrets or trufflehog to scan your commits locally before they are ever pushed to a remote server.The Fix: What to Do When You Find a Secret
If you discover a secret in your codebase, deleting the file or removing the line of code and committing the change is not enough. The secret will still exist in your Git history.
Here is the exact protocol to follow:
Step 1: Rotate the Secret Immediately
Assume the secret is already compromised. Go to the provider (Stripe, AWS, Supabase, etc.) and generate a new key. Revoke the old key. This is the only way to guarantee your application is safe.Step 2: Move the Secret to Environment Variables
Update your code to read the configuration from environment variables.typescript
// Bad
const stripe = new Stripe('sk_live_123456789');
// Good
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
Step 3: Update .gitignore
Ensure that your.env file is explicitly listed in your .gitignore file. You should only commit a .env.example file that contains empty variable names.
Step 4: Scrub Your Git History (Optional but Recommended)
If the repository is private and the key has been rotated, the immediate threat is neutralized. However, it is best practice to scrub the secret from your history using a tool like BFG Repo-Cleaner orgit filter-repo. Be warned: this rewrites your git history and will require all collaborators to force-pull.
Want CodeAudit to check your repo for this automatically? Join the waitlist.
Frequently Asked Questions
Q: Are secrets safe if my GitHub repository is private? A: No. Private repositories can be accidentally made public, employee laptops can be compromised, and third-party integrations can leak data. Assume any committed secret is exposed.
Q: Can I just delete the commit?
A: Standard git commands like git revert or deleting the line only add a new commit. The secret remains fully accessible in the commit history. You must use history-rewriting tools.
Q: How does CodeAudit handle secrets? A: CodeAudit scans your codebase for over 150 types of secrets, high-entropy strings, and common credential patterns, delivering actionable reports before you deploy.
Want CodeAudit to check your repo for this automatically? Join the waitlist.
System Check Required
RUN CODEAUDIT BEFORE DEPLOYMENT. AVOID CRITICAL FAILURES. JOIN THE QUEUE.
[ INITIALIZE AUDIT ]