-
NEVER hardcode API keys, tokens, or secrets in code
- β
const API_KEY = "sk-123456789" - β
const API_KEY = process.env.API_KEY(Node.js) - β
API_KEY = os.getenv("API_KEY")(Python)
- β
-
ALL credentials MUST be in .env files ONLY
.env- Real credentials (gitignored).env.local- Local overrides (gitignored).env.example- Placeholders only (tracked in git)
-
NEVER commit .env files to git
- Already protected by
.gitignore - Double-check before every commit:
git status
- Already protected by
These files contain secrets and are automatically ignored by git:
.env
.env.local
.env.*.local
*.db
*.sqlite
optimizer.db
Before every commit, verify:
- No API keys in code files (
.py,.ts,.js) - All secrets loaded from
process.envoros.getenv() -
.envfiles not staged for commit - Only
.env.examplecontains placeholders - No database files committed
# Check staged files for API key patterns
git diff --cached | grep -E "sk-[a-zA-Z0-9]{48}|AIza[a-zA-Z0-9_-]{35}|eyJ[a-zA-Z0-9_-]*\."
# If any matches found - STOP! Remove the keys before committing# Scan all Python/JS/TS files for hardcoded keys
grep -r "API_KEY\s*=\s*['\"]" --include="*.py" --include="*.js" --include="*.ts" --exclude-dir=node_modules --exclude-dir=.venv .
# Should return empty or only examples/comments# Check if .env was ever committed
git log --all --full-history -- "*.env"
# If found, you need to:
# 1. Rotate all exposed keys immediately
# 2. Use git-filter-repo or BFG Repo-Cleaner to remove from history-
STOP! Do not push to GitHub (if not pushed yet)
-
Rotate ALL exposed API keys immediately:
- Supabase: Project Settings β API β Generate new service role key
- OpenRouter: https://openrouter.ai/keys β Revoke & create new
- Anthropic: https://console.anthropic.com/settings/keys
- Google AI: https://aistudio.google.com/app/apikey
-
Remove from git history:
# Install git-filter-repo pip install git-filter-repo # Remove .env from all commits git-filter-repo --invert-paths --path .env # Force push (ONLY if safe) git push origin --force --all
-
Update .env with new keys
-
Notify team if shared repository
import os
from dotenv import load_dotenv
load_dotenv() # Load from .env file
# CORRECT β
API_KEY = os.getenv("OPENROUTER_API_KEY")
SUPABASE_URL = os.getenv("SUPABASE_URL")
# INCORRECT β - Never do this!
# API_KEY = "sk-or-v1-abc123..."// CORRECT β
const apiKey = process.env.OPENROUTER_API_KEY
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
// INCORRECT β - Never do this!
// const apiKey = "sk-or-v1-abc123..."Project Root:
βββ .env β Your real secrets (gitignored)
βββ .env.local β Local dev overrides (gitignored)
βββ .env.example β Template with placeholders (tracked in git)
βββ .gitignore β Protects .env files
Create .git/hooks/pre-commit to automatically block commits with secrets:
#!/bin/bash
# Scan staged files for API key patterns
if git diff --cached --diff-filter=ACM | grep -qE "sk-[a-zA-Z0-9]{48}|AIza[a-zA-Z0-9_-]{35}|eyJ[a-zA-Z0-9_-]*\."; then
echo "β ERROR: Potential API key detected in staged changes!"
echo "Please remove hardcoded credentials before committing."
exit 1
fi
# Check if .env files are staged
if git diff --cached --name-only | grep -qE "^\.env$|^\.env\.local$"; then
echo "β ERROR: .env file staged for commit!"
echo "Remove it with: git reset HEAD .env"
exit 1
fi
echo "β
Pre-commit security check passed"
exit 0Make it executable:
chmod +x .git/hooks/pre-commit# Install
brew install git-secrets # macOS
# or: https://github.com/awslabs/git-secrets
# Setup
git secrets --install
git secrets --register-aws
git secrets --add 'sk-[a-zA-Z0-9]{48}'
git secrets --add 'eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*'# Install
brew install gitleaks # macOS
# Scan repository
gitleaks detect --source . --verbose
# Scan before commit
gitleaks protect --staged# Install
brew install trufflehog # macOS
# Scan entire git history
trufflehog git file://. --only-verified-
Immediate (< 5 min):
- Revoke all exposed keys
- Generate new keys
- Update .env locally
-
Short-term (< 1 hour):
- Remove from git history using git-filter-repo
- Force push cleaned history
- Verify keys are gone:
git log --all --full-history -- "*.env"
-
Long-term:
- Install pre-commit hooks
- Add gitleaks to CI/CD pipeline
- Team training on secret management
- Supabase: Dashboard β Project Settings β API
- OpenRouter: https://openrouter.ai/keys
- Anthropic: https://console.anthropic.com/settings/keys
- Google AI: https://aistudio.google.com/app/apikey
- Cerebras: https://cloud.cerebras.ai/
- Cartesia: https://cartesia.ai/dashboard
- Use different keys for dev/staging/production
- Rotate keys every 90 days
- Never share .env files via Slack/email
- Use 1Password / Bitwarden for team secret sharing
- Enable 2FA on all provider accounts
- Monitor API key usage for anomalies
- Set spending limits on all API providers
Last Updated: 2025-01-17 Incident Count: 1 (2025-01-XX - .env committed to GitHub, keys rotated)