Skip to main content

Leaked Secret Response

Immediate Actions (Within 1 Hour)​

1. Assume Compromised (Do Not Delay)​

The secret is compromised the moment it's pushed to Git, even if the repo is private.

2. Rotate the Secret Immediately​

Stop the bleeding first, investigate later.

# Example: Database password leaked
# 1. Change password at source
psql -U postgres -c "ALTER USER appuser PASSWORD 'new_secure_password_123!';"

# 2. Update Ansible Vault
ansible-vault edit inventory/production/group_vars/all/vault.yml
# Change vault_db_password to new password

# 3. Update GitHub Secrets (if used in CI/CD)
# Go to repo Settings → Secrets → Update DB_PASSWORD

# 4. Redeploy affected services with new secret
ansible-playbook playbooks/deploy.yml -i inventory/production

Timeline: Complete rotation within 1 hour of discovery.

3. Alert Security Team​

# In Rocket.Chat #security channel
⚠️ Secret leaked in Git
Repo: company/api-server
Commit: abc123def
Secret type: Database password
Action taken: Rotated immediately
Status: Investigating

4. Identify What Was Exposed​

Check:

  • What secret? (password, API key, private key?)
  • Where? (which repo, which commit?)
  • When? (commit timestamp)
  • Who had access? (public repo? private? team members?)
  • Was it pushed to GitHub? (yes = assume public)

Secret-Specific Rotation​

Database Password​

# 1. Change at database
ALTER USER appuser PASSWORD 'new_password';

# 2. Update in Ansible Vault
ansible-vault edit inventory/production/group_vars/databases/vault.yml

# 3. Update running services
ansible-playbook playbooks/update-db-config.yml -i inventory/production

# 4. Verify connectivity
ansible all -i inventory/production -m shell -a "psql -U appuser -c 'SELECT 1;'"

API Key (Third-Party Service)​

# 1. Revoke old key in provider dashboard (e.g., Stripe, SendGrid)
# 2. Generate new API key
# 3. Update in Ansible Vault + GitHub Secrets
ansible-vault edit inventory/production/group_vars/all/vault.yml
# Update GitHub repo Settings → Secrets

# 4. Redeploy services
ansible-playbook playbooks/deploy.yml -i inventory/production

SSH Private Key​

# 1. Remove public key from all servers
ansible-playbook playbooks/remove-ssh-key.yml -e "ssh_key_fingerprint=XX:YY:ZZ"

# 2. Generate new key pair
ssh-keygen -t ed25519 -C "[email protected]"

# 3. Add new public key to authorized_keys via Ansible
# Update inventory/production/group_vars/all/users.yml
ansible-playbook playbooks/sync-ssh-keys.yml -i inventory/production

# 4. Update key in GitHub Secrets (for CI/CD)

SSL/TLS Private Key​

# 1. Revoke certificate immediately
# Contact certificate authority to revoke

# 2. Generate new CSR and private key
openssl req -new -newkey rsa:2048 -nodes -keyout new.key -out new.csr

# 3. Obtain new certificate

# 4. Deploy via Ansible
ansible-playbook playbooks/update-ssl-certs.yml -i inventory/production

OAuth Token / JWT Secret​

# 1. Rotate signing key
# Generate new secret key

# 2. Update in Ansible Vault + GitHub Secrets
ansible-vault edit inventory/production/group_vars/all/vault.yml

# 3. Deploy new config
ansible-playbook playbooks/deploy.yml -i inventory/production

# 4. Invalidate all existing tokens (force re-login)
# Depends on your auth system

Clean Git History​

After rotating, clean the secret from Git history:

# Option 1: Using git-filter-repo (recommended)
pip install git-filter-repo
git filter-repo --path-glob '**/secrets.yml' --invert-paths

# Option 2: Using BFG Repo-Cleaner
# Download BFG: https://rtyley.github.io/bfg-repo-cleaner/
java -jar bfg.jar --delete-files secrets.yml
git reflog expire --expire=now --all
git gc --prune=now --aggressive

# Force push (⚠️ Notify team first!)
git push --force --all
git push --force --tags

⚠️ Warning: Force push rewrites history. Coordinate with team.

Incident Report​

Document in post-incident review:

  1. What was leaked: Type of secret, service it belongs to
  2. How it was leaked: Accidental commit, wrong .gitignore, etc.
  3. When detected: Timestamp
  4. Exposure window: Time between leak and rotation
  5. Rotation completed: Timestamp
  6. Evidence of use: Any logs showing unauthorized access?
  7. Prevention: What we'll do differently

Template:

## Secret Leak Incident - YYYY-MM-DD

**Secret**: Production database password
**Leaked in**: Commit abc123 on 2025-11-10 14:23
**Detected**: 2025-11-10 14:35 (12 minutes exposure)
**Rotated**: 2025-11-10 14:47 (24 minutes from leak)
**Evidence of compromise**: None found in access logs
**Cleaned from Git**: Yes, force push at 14:55

**Root cause**: Developer committed .env file (should be in .gitignore)

**Prevention**:
- Added .env to global .gitignore
- Enabled pre-commit hook for secret scanning
- Added to onboarding checklist
- Scheduled training on secret management

Prevention Measures​

After handling the incident, implement these to prevent recurrence:

1. Pre-Commit Hooks (Blocks commits)​

# Install gitleaks pre-commit hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks

# Install for all developers
pre-commit install

2. GitHub Secret Scanning (Already Active)​

Already enabled on GitHub. Ensure Rocket.Chat webhook configured for alerts.

3. Update .gitignore​

# Add to .gitignore
.env
.env.*
*.secret
*.key
*.pem
vault-password.txt
credentials.json

4. Code Review Checklist​

Add to PR template:

  • No secrets in code
  • .env files in .gitignore
  • Secrets stored in Ansible Vault or GitHub Secrets
  • Pre-commit hooks passing

5. Developer Training​

  • Add to onboarding: "Secret Management 101"
  • Regular reminders in #engineering channel
  • Share incident reports as learning

Monitoring for Unauthorized Use​

After rotation, watch for:

# Check access logs for unauthorized access
# Example: Database connection logs
grep "authentication failed" /var/log/postgresql/postgresql.log

# Check API logs for old API key usage
grep "401 Unauthorized" /var/log/app/api.log | grep "old_api_key"

# Monitor for unusual activity
# - Login attempts from unknown IPs
# - Access to sensitive data
# - Unusual query patterns

Alert #security if suspicious activity detected.