IA /

Sección de IA

Descripción

Los hooks de Claude Code resultan especialmente útiles cuando se integran dentro de scripts propios, porque permiten controlar con precisión qué partes del contenido se procesan, cómo se transforman y en qué momento se ejecutan. Al encapsular la lógica en un script, puedes definir flujos más complejos, validar entradas, aplicar filtros o incluso combinar varias herramientas antes de invocar el hook. Esto te da un nivel de control que sería difícil de lograr si dependieras únicamente de llamadas directas y manuales. Además, trabajar con scripts facilita la trazabilidad y el versionado del comportamiento, algo esencial cuando buscas estabilidad y repetibilidad en tus automatizaciones.

Otro beneficio clave es que los scripts hacen que el uso de los hooks sea independiente de la plataforma, lo que significa que puedes ejecutarlos en cualquier entorno que soporte tu lenguaje de scripting preferido: Linux, Windows, macOS o incluso contenedores. Esto elimina dependencias innecesarias y te permite integrar Claude Code en pipelines CI/CD, tareas programadas o herramientas internas sin preocuparte por la compatibilidad. En resumen, usar hooks dentro de scripts convierte a Claude Code en una pieza modular, portable y mucho más flexible dentro de tu ecosistema técnico.

settings.json

  1. "hooks" : {
  2.      "PreToolUse" : [
  3.          {
  4.            "matcher" : "Bash|Edit|Multiedit|Write" ,
  5.            "hooks" : [
  6.                {
  7.                   "type"   : "command",
  8.                   "command": "python \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/security_gate.py"
  9.                    }
  10.                ]
  11.          }
  12.  
  13.          ]
  14.  
  15.     }

Python Script

  1. #!/usr/bin/env python3
  2. """
  3. PreToolUse hook: Security gate para PayFlow API.
  4. Bloquea comandos peligrosos y acceso a archivos sensibles.
  5. Usa JSON decision control (permissionDecision) para dar razones claras.
  6. """
  7. import sys
  8. import json
  9. import re
  10.  
  11.  
  12. def check_bash_command(cmd: str) -> tuple[bool, str]:
  13.     """Verifica si un comando Bash es seguro. Retorna (bloqueado, razón)."""
  14.     dangerous_patterns = [
  15.         (r"rm\s+(-[rf]+\s+|.*--no-preserve-root)", "Borrado recursivo/forzado"),
  16.         (r"git\s+(reset\s+--hard|push\s+(-f|--force))", "Operación git destructiva"),
  17.         (r"sudo\s+", "Ejecución con privilegios elevados"),
  18.         (r"chmod\s+777", "Permisos excesivamente permisivos"),
  19.         (r"(curl|wget).*\|\s*(ba)?sh", "Ejecución de script remoto por pipe"),
  20.         (r"DROP\s+(TABLE|DATABASE)", "Borrado de estructura de BD"),
  21.         (r"DELETE\s+FROM\s+\w+\s*;?\s*$", "DELETE sin WHERE"),
  22.     ]
  23.     for pattern, reason in dangerous_patterns:
  24.         if re.search(pattern, cmd, re.IGNORECASE):
  25.             return True, reason
  26.  
  27.     sensitive_files = [
  28.         ".env", ".env.local", ".env.production",
  29.         "id_rsa", "id_ed25519", ".pem", ".key",
  30.     ]
  31.     for f in sensitive_files:
  32.         if f in cmd:
  33.             return True, f"Acceso a archivo sensible: {f}"
  34.  
  35.     prod_patterns = [
  36.         (r"(psql|mysql|mongo).*prod", "Cliente de BD apuntando a producción"),
  37.         (r"ssh.*prod", "SSH a servidor de producción"),
  38.     ]
  39.     for pattern, reason in prod_patterns:
  40.         if re.search(pattern, cmd, re.IGNORECASE):
  41.             return True, reason
  42.  
  43.     return False, ""
  44.  
  45.  
  46. def check_file_write(file_path: str) -> tuple[bool, str]:
  47.     """Verifica si la escritura a un archivo es segura."""
  48.     protected = [
  49.         (r"\.env($|\.)", "Archivo de variables de entorno"),
  50.         (r"(id_rsa|id_ed25519|\.pem|\.key)$", "Archivo de claves privadas"),
  51.         (r"alembic/versions/.*\.py$", "Migración de BD (requiere revisión manual)"),
  52.     ]
  53.     for pattern, reason in protected:
  54.         if re.search(pattern, file_path, re.IGNORECASE):
  55.             return True, reason
  56.     return False, ""
  57.  
  58.  
  59. def main():
  60.     input_data = json.load(sys.stdin)
  61.     tool_name = input_data.get("tool_name", "")
  62.     tool_input = input_data.get("tool_input", {})
  63.  
  64.     blocked = False
  65.     reason = ""
  66.  
  67.     if tool_name == "Bash":
  68.         blocked, reason = check_bash_command(tool_input.get("command", ""))
  69.     elif tool_name in ("Write", "Edit", "MultiEdit"):
  70.         blocked, reason = check_file_write(tool_input.get("file_path", ""))
  71.  
  72.     if blocked:
  73.         json.dump({
  74.             "hookSpecificOutput": {
  75.                 "hookEventName": "PreToolUse",
  76.                 "permissionDecision": "deny",
  77.                 "permissionDecisionReason": f"Bloqueado por política de seguridad: {reason}"
  78.             }
  79.         }, sys.stdout)
  80.  
  81.     sys.exit(0)
  82.  
  83.  
  84. if __name__ == "__main__":
  85.     main()

IA : Prompts : Claude : Copilot

Última modificación de la página el 20 May 2026 a las 12h09
Powered by PmWiki