PostToolUse hook que detecta passwords y API keys hardcodeadas en archivos escritos.
# Archivo: .claude/hooks/security-scanner.py
# Evento: PostToolUse (matcher: Write|Edit)
#!/usr/bin/env python3
import json
import sys
import re
SECRET_PATTERNS = [
(r'password\s*=\s*['"][^'"]+['"]', "Password hardcodeada detectada"),
(r'api[_-]?key\s*=\s*['"][^'"]{8,}['"]', "API key hardcodeada detectada"),
(r'secret\s*=\s*['"][^'"]{8,}['"]', "Secret hardcodeado detectado"),
(r'bearer\s+[a-zA-Z0-9_\-\.]+', "Bearer token en código"),
(r'sk-[a-zA-Z0-9]{32,}', "Posible OpenAI/Anthropic API key"),
]
def main():
data = json.load(sys.stdin)
if data.get("tool_name") not in ["Write", "Edit"]:
sys.exit(0)
tool_input = data.get("tool_input", {})
content = tool_input.get("content", "") or tool_input.get("new_string", "")
file_path = tool_input.get("file_path", "")
# Ignorar archivos de entorno y test fixtures
if any(x in file_path for x in [".env", "fixture", "test/mock"]):
sys.exit(0)
warnings = []
for pattern, message in SECRET_PATTERNS:
if re.search(pattern, content, re.IGNORECASE):
warnings.append(message)
if warnings:
output = {
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": f"⚠️ {file_path}: " + " | ".join(warnings) +
" — Usa process.env en su lugar."
}
}
print(json.dumps(output))
sys.exit(0)
if __name__ == "__main__":
main()