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.

Medium Python 3.9+ Aug 9, 2026 Git + Python 14 views 0 copies

Python code

66 lines
Python 3.9+
#!/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

stdout
=== 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

  1. Use `os.walk()` instead of `Path.rglob` for older Python compatibility
  2. 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

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Git + Python

Related tutorials and quizzes for this topic.