Python Script to Rotate a Leaked API Key
A checklist-driven Python script that scans a codebase for a leaked API key, replaces it with a new one, and prints a step-by-step rotation checklist.
Python code
66 lines#!/usr/bin/env python3
"""Checklist for rotating a leaked API key across a codebase."""
import re
from pathlib import Path
CHECKLIST = [
"Identify all files containing the leaked key",
"Generate a new key with sufficient entropy",
"Update the secret storage/CI environment variables",
"Replace the old key in every source file",
"Test authentication with the new key",
"Revoke the leaked key immediately after rotation",
"Audit logs for any unauthorized use before rotation",
"Rotate again if the leaked key was committed to git history",
]
def find_key_occurrences(directory: str, key: str) -> list[str]:
"""Return file paths that contain the given key."""
matches = []
pattern = re.compile(re.escape(key))
for path in Path(directory).rglob("*"):
if path.is_file() and not path.name.startswith("."):
try:
if pattern.search(path.read_text(errors="ignore")):
matches.append(str(path))
except (OSError, UnicodeDecodeError):
continue
return matches
def rotate_key_in_file(filepath: str, old_key: str, new_key: str) -> bool:
"""Replace old_key with new_key in a single file."""
path = Path(filepath)
try:
content = path.read_text(errors="strict")
except (OSError, UnicodeDecodeError):
return False
if old_key not in content:
return False
path.write_text(content.replace(old_key, new_key))
return True
if __name__ == "__main__":
OLD_KEY = "sk-live-1234567890abcdef"
NEW_KEY = "sk-live-abcdef1234567890"
print("=== LEAKED KEY ROTATION CHECKLIST ===")
for idx, item in enumerate(CHECKLIST, start=1):
print(f"{idx}. {item}")
print("\n=== DEMO: Scanning current directory ===")
affected_files = find_key_occurrences(".", OLD_KEY)
if affected_files:
print(f"Found leaked key in {len(affected_files)} file(s):")
for f in affected_files:
print(f" - {f}")
rotated = rotate_key_in_file(f, OLD_KEY, NEW_KEY)
print(f" rotated: {rotated}")
else:
print(f"No files contain the leaked key ({OLD_KEY})")
Output
=== LEAKED KEY ROTATION CHECKLIST ===
1. Identify all files containing the leaked key
2. Generate a new key with sufficient entropy
3. Update the secret storage/CI environment variables
4. Replace the old key in every source file
5. Test authentication with the new key
6. Revoke the leaked key immediately after rotation
7. Audit logs for any unauthorized use before rotation
8. Rotate again if the leaked key was committed to git history
=== DEMO: Scanning current directory ===
No files contain the leaked key (sk-live-1234567890abcdef)
How it works
The script uses a regex with re.escape to safely search for the key, avoiding false matches from regex special characters. It walks the directory tree with Path.rglob and reads files as text, skipping binary files and errors gracefully. The rotation function replaces all occurrences of the old key in each affected file atomically. The checklist is printed as a procedural reminder to follow security best practices beyond just code replacement, including revoking the key and auditing logs.
Common mistakes
- Forgetting to revoke the old key after rotation
- Skipping git history scanning when the key was committed
- Not using `re.escape` for literal key search, causing regex errors
- Overwriting files without reading binary-safe content
Variations
- Use `os.walk()` instead of `Path.rglob` for older Python compatibility
- Add `git log -S` to scan commit history for the leaked key
Real-world use cases
- Automating credential rotation across microservices after a security incident.
- Ensuring CI/CD secrets are updated before redeploying services.
- Pre-commit hygiene to remove leaked keys from monorepos before pushing.
Sponsored
More from Git + Python
- Amend Last Commit Message in Python easy
- Bisect Good Bad Automation Script in Python easy
- Build a Simple Log Graph in Python easy
- Bump Semantic Version Git Tag in Python easy
- Count Unique Contributors from Git Shortlog in Python easy
- Create a Mock GitHub Release API in Python for Testing gh CLI easy
Keep learning
Related tutorials and quizzes for this topic.