- β
.env - β
.env.local - β
.env.production - β
backend/.env - β
env.example(template only) - β
env.local.example(template only)
These should ONLY be in .env files (which are gitignored):
- Supabase URL and keys
- Stripe secret keys
- Redis URLs with passwords
- Docker registry tokens
- Email provider API keys
- JWT secret keys
- Webhook secrets
- Database passwords
- β
secrets.json - β
credentials.json - β
*.pem(private keys) - β
*.key(SSL/TLS keys) - β
*.cert(certificates) - β
dump.rdb(Redis dump - may contain session data) - β
*.sqlite(local databases)
- β
env.example- Template with placeholder values - β
requirements.txt- Python dependencies (no secrets) - β
package.json- Node dependencies (no secrets) - β
*.md- Documentation - β Source code files
- β
schema.sql- Database structure (no data) - β
.gitignoreitself
-
.gitignorefiles are in place -
.envfiles are NOT tracked - No hardcoded API keys in source code
- All secrets use environment variables
- Example env files have placeholder values
# Check what's being committed
git status
# Look for sensitive files
git diff
# Check for accidentally staged secrets
git diff --cached
# Search for potential secrets
grep -r "sk_live_" .
grep -r "api_key" .
grep -r "password" .IMMEDIATELY:
-
Rotate ALL exposed credentials
# Change in respective services: # - Stripe: Generate new API keys # - Supabase: Rotate keys # - Redis: Change password # - Email: Generate new API key
-
Remove from Git history
# Use git-filter-repo or BFG Repo-Cleaner # DO NOT just delete the file - it's still in history! # Option 1: BFG Repo-Cleaner (recommended) bfg --delete-files .env git reflog expire --expire=now --all git gc --prune=now --aggressive # Option 2: git filter-repo git filter-repo --invert-paths --path .env
-
Force push (if already pushed)
git push --force # WARNING: Coordinate with team first!
# Install
brew install git-secrets # macOS
# or download from: https://github.com/awslabs/git-secrets
# Setup in repo
cd /path/to/repo
git secrets --install
git secrets --register-aws
# Add custom patterns
git secrets --add 'sk_live_[a-zA-Z0-9]{24}' # Stripe live keys
git secrets --add 'sk_test_[a-zA-Z0-9]{24}' # Stripe test keys
git secrets --add 'eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*' # JWT tokens
git secrets --add 'supabase_[a-zA-Z0-9]{40}' # Supabase keys# Install
brew install gitleaks
# Scan repository
gitleaks detect --source . --verbose
# Scan before commit
gitleaks protect --staged --verbose# Backend
cp backend/env.example backend/.env
# Edit backend/.env with your development credentials
# Frontend
cp env.local.example .env.local
# Edit .env.local with your development credentialsNever store production secrets in code!
Use environment variable management:
- Vercel: Dashboard β Project Settings β Environment Variables
- Render: Dashboard β Environment β Add Environment Variable
- GitHub Actions: Repository Settings β Secrets and Variables
- Docker: Use secrets or env files (not in image)
| Secret | Used For | Risk if Exposed |
|---|---|---|
STRIPE_SECRET_KEY |
Process payments | Financial fraud |
SUPABASE_SERVICE_KEY |
Bypass RLS, admin access | Full database access |
JWT_SECRET_KEY |
Sign auth tokens | Account takeover |
STRIPE_WEBHOOK_SECRET |
Verify webhooks | Fake payment events |
| Secret | Used For | Risk if Exposed |
|---|---|---|
DOCKER_REGISTRY_TOKEN |
Push/pull images | Unauthorized downloads |
EMAIL_PROVIDER_API_KEY |
Send emails | Spam from your account |
REDIS_URL (with password) |
Cache access | Session hijacking |
| Secret | Used For | Risk if Exposed |
|---|---|---|
SUPABASE_ANON_KEY |
Client-side auth | Limited (RLS protected) |
STRIPE_PUBLISHABLE_KEY |
Client-side Stripe | Read-only, low risk |
# β NEVER DO THIS
stripe.api_key = "sk_live_abc123..."
# β
DO THIS
from config import settings
stripe.api_key = settings.stripe_secret_key// β NEVER DO THIS
const apiKey = "pk_live_abc123..."
// β
DO THIS
const apiKey = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY# Check if .env is ignored
git check-ignore backend/.env
# Should output: backend/.env
# If not ignored, check .gitignore
cat .gitignore | grep ".env"Create .git/hooks/pre-commit:
#!/bin/bash
# Check for .env files
if git diff --cached --name-only | grep -E "\.env$|\.env\.local$"; then
echo "β ERROR: Attempting to commit .env file!"
echo "Please remove it from staging:"
echo " git reset HEAD .env"
exit 1
fi
# Check for hardcoded secrets
if git diff --cached | grep -E "sk_live_|sk_test_|eyJ[a-zA-Z0-9]"; then
echo "β οΈ WARNING: Potential secret detected in commit!"
echo "Please review your changes carefully."
read -p "Continue anyway? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
exit 0Make it executable:
chmod +x .git/hooks/pre-commit- STOP - Don't commit/push anymore
- ASSESS - What was exposed?
- ROTATE - Change ALL exposed credentials
- REMOVE - Clean Git history
- AUDIT - Check for unauthorized access
- MONITOR - Watch for suspicious activity
- NOTIFY - Inform team/users if needed
Stripe:
- Dashboard β Developers β API keys
- Click "Reveal test/live key"
- Roll keys
- Update
.envfiles - Redeploy
Supabase:
- Project Settings β API
- Click "Generate new anon key"
- Click "Generate new service key"
- Update
.envfiles - Redeploy
Redis:
- Update password in Redis provider
- Update
REDIS_URLin.env - Restart services
# Check gitignore is working
git status --ignored
# Verify .env is not tracked
git ls-files | grep ".env"
# Should return nothing
# Check for secrets in code
grep -r "sk_live_" . --exclude-dir=node_modules --exclude-dir=.git
grep -r "sk_test_" . --exclude-dir=node_modules --exclude-dir=.git
# Verify example files only
ls -la | grep env
# Should show: env.example, env.local.example
# Should NOT show: .env, .env.localEveryone on the team should:
- Read this document
- Understand which files contain secrets
- Know how to use
.envfiles - Install
git-secretsorgitleaks - Review commits before pushing
- Know the emergency response plan
The three rules of secrets:
- Never commit secrets to Git (use .env files)
- Never hardcode secrets in code (use environment variables)
- Never share secrets in chat/email (use secure secret management)
Stay secure! π‘οΈ