{"meta":{"title":"Uso de enlaces con Copilot CLI para una ejecución predecible y compatible con directivas","intro":"Use enlaces para registrar las solicitudes del usuario y controlar qué herramientas Copilot CLI se pueden ejecutar en un repositorio, por lo que los equipos pueden automatizar de forma segura dentro de los requisitos de seguridad y cumplimiento de su organización.","product":"GitHub Copilot","breadcrumbs":[{"href":"/es/copilot","title":"GitHub Copilot"},{"href":"/es/copilot/tutorials","title":"Tutoriales"},{"href":"/es/copilot/tutorials/copilot-cli-hooks","title":"Uso de enlaces con la CLI de Copilot"}],"documentType":"article"},"body":"# Uso de enlaces con Copilot CLI para una ejecución predecible y compatible con directivas\n\nUse enlaces para registrar las solicitudes del usuario y controlar qué herramientas Copilot CLI se pueden ejecutar en un repositorio, por lo que los equipos pueden automatizar de forma segura dentro de los requisitos de seguridad y cumplimiento de su organización.\n\nEste tutorial es para ingenieros DevOps, equipos de plataforma y líderes de ingeniería que apoyan a los desarrolladores que usan Copilot CLI.\n\nLos enlaces son scripts personalizados que se ejecutan en puntos específicos durante una sesión de Copilot CLI. Pueden inspeccionar las indicaciones y las llamadas a herramientas, los registros de auditoría e incluso bloquear la ejecución de ciertos comandos.\n\nConfigurará enlaces con ámbito de repositorio que:\n\n* Proporcionar visibilidad de las indicaciones y el uso de herramientas.\n* Bloquear patrones de comandos de alto riesgo antes de la ejecución.\n* Ayude a los desarrolladores a comprender las directivas de la organización con mensajería clara.\n\n## Prerrequisitos\n\n* Conocimientos de creación de scripts de shell (Bash o PowerShell).\n* Conocimientos básicos de los archivos de configuración JSON.\n* Acceso a un repositorio donde Copilot CLI se usa.\n* Para los ejemplos de Bash: `jq` debe instalarse.\n* Para ver los ejemplos de PowerShell: Se debe instalar PowerShell 7.0 o posterior.\n\n## 1. Definir una directiva organizativa\n\nAntes de escribir scripts de enlace, decida qué acciones se deben permitir automáticamente y cuáles deben requerir revisión humana.\n\nUna directiva clara le ayuda a evitar el exceso de bloqueo mientras sigue reduciendo el riesgo.\n\n### Identificación de comandos que siempre requieren revisión\n\nEmpiece por identificar patrones que nunca se deben ejecutar automáticamente mediante Copilot CLI. Algunos ejemplos habituales:\n\n* **Escalación de privilegios**: `sudo`, `su`, `runas`\n* **Operaciones destructivas del sistema**: `rm -rf /`, `mkfs`, `dd`, `format`\n* **Patrones de descarga y ejecución**: `curl ... | bash`, `wget ... | sh`, PowerShell `iex (irm ...)`\n\nEstos comandos pueden tener efectos irreversibles si se ejecutan involuntariamente.\n\n### Decidir qué registrar\n\nAl usar ganchos, puede capturar información sobre cómo Copilot CLI se utiliza en un repositorio, incluidas las solicitudes enviadas por usuarios y herramientas que Copilot CLI intenta ejecutar.\n\nComo mínimo, la mayoría de las organizaciones registran:\n\n* La marca de tiempo y la ruta de acceso del repositorio\n* Texto del mensaje (o un formulario redactado)\n* El nombre de la herramienta y los argumentos de la herramienta\n* Cualquier decisión de directiva (por ejemplo, un comando denegado y su motivo)\n\nEvite registrar secretos o credenciales. Si los mensajes o comandos pueden contener datos confidenciales, aplique la redacción antes de escribir registros.\n\nEn este tutorial se usa un directorio local `.github/hooks/logs` como ejemplo ilustrativo sencillo. Estos archivos de registro **no están diseñados para subirse al repositorio** y normalmente viven solo en la máquina de un desarrollador.\n\nEn entornos de producción, muchas organizaciones reenvía eventos de enlace a un sistema centralizado de registro o observabilidad en lugar de escribir registros localmente. Esto permite a los equipos aplicar una redacción coherente, controles de acceso, directivas de retención y supervisión de manera consistente en repositorios y usuarios.\n\n### Alineación con las partes interesadas\n\nAntes de aplicar políticas, repáselas con:\n\n* Equipos de seguridad o cumplimiento para confirmar límites de riesgo\n* Equipos de plataforma o infraestructura, que pueden necesitar permisos más amplios\n* Equipos de desarrollo, para que comprendan qué se bloqueará y por qué\n\nLas expectativas claras facilitan la adopción y el mantenimiento de las directivas.\n\n## 2. Configurar archivos de enlace de repositorio\n\nEn este tutorial, utilizará **enlaces con ámbito de repositorio** almacenados en el repositorio, en `.github/hooks/`. Estos ganchos se aplican cada vez que Copilot CLI se ejecuta desde este repositorio.\n\n> \\[!NOTE]\n> Los agentes de Copilot cargan configuraciones de enlaces desde archivos `.github/hooks/*.json` en el repositorio. Los hooks se ejecutan sincrónicamente y pueden bloquear la ejecución.\n\n### Creación de la estructura de directorios\n\nEn la raíz del repositorio, cree directorios para la configuración del hook, los scripts y los registros.\n\n```bash copy\nmkdir -p .github/hooks/scripts\nmkdir -p .github/hooks/logs\n```\n\nAgregue `.github/hooks/logs/` a .gitignore para que no se confirmen los registros de auditoría locales:\n\n```bash copy\necho \".github/hooks/logs/\" >> .gitignore\n```\n\nEn este tutorial se usa la siguiente estructura:\n\n```text\n.github/\n└── hooks/\n    ├── copilot-cli-policy.json\n    ├── logs/\n    │   └── audit.jsonl\n    └── scripts/\n        ├── session-banner.sh\n        ├── session-banner.ps1\n        ├── log-prompt.sh\n        ├── log-prompt.ps1\n        ├── pre-tool-policy.sh\n        └── pre-tool-policy.ps1\n```\n\n> \\[!NOTE]\n> En este tutorial se buscan crear configuraciones de enlace portátiles y scripts que se pueden usar en Windows, Linux y macOS. Por lo tanto, el directorio `scripts` contendrá tanto scripts de Bash como de PowerShell, y los archivos de configuración de hooks incluirán entradas `bash` y `powershell`. La CLI usará la entrada adecuada en función del sistema operativo.\n\n### Creación de un archivo de configuración de enlace\n\nCree un archivo de configuración de enlace en `.github/hooks/copilot-cli-policy.json`.\n\nEste archivo define cuáles ganchos se ejecutan, cuándo se activan y qué scripts ejecutan.\n\n```json copy\n{\n  \"version\": 1,\n  \"hooks\": {\n    \"sessionStart\": [\n      {\n        \"type\": \"command\",\n        \"bash\": \"./scripts/session-banner.sh\",\n        \"powershell\": \"./scripts/session-banner.ps1\",\n        \"cwd\": \".github/hooks\",\n        \"timeoutSec\": 10\n      }\n    ],\n    \"userPromptSubmitted\": [\n      {\n        \"type\": \"command\",\n        \"bash\": \"./scripts/log-prompt.sh\",\n        \"powershell\": \"./scripts/log-prompt.ps1\",\n        \"cwd\": \".github/hooks\",\n        \"timeoutSec\": 10\n      }\n    ],\n    \"preToolUse\": [\n      {\n        \"type\": \"command\",\n        \"bash\": \"./scripts/pre-tool-policy.sh\",\n        \"powershell\": \"./scripts/pre-tool-policy.ps1\",\n        \"cwd\": \".github/hooks\",\n        \"timeoutSec\": 15\n      }\n    ]\n  }\n}\n```\n\n### Comprender lo que hace esta configuración\n\nEsta configuración configura tres ganchos:\n\n* `sessionStart`: muestra un mensaje informativo cuando se inicia o reanuda una nueva sesión del agente.\n* `userPromptSubmitted`: se ejecuta cada vez que un usuario envía un mensaje.\n* `preToolUse`: se ejecuta antes de que una herramienta se ejecute y pueda permitir o denegar explícitamente la ejecución.\n\n### Confirmar y compartir la configuración del enlace\n\nCuando esté listo para compartir la configuración de enlace con colaboradores (por ejemplo, a través de una solicitud de incorporación de cambios o en un repositorio de pruebas), confirme la configuración y los scripts del enlace. No guarde ningún registro de auditoría local.\n\n```bash copy\ngit add .github/hooks/copilot-cli-policy.json .github/hooks/scripts\ngit commit -m \"Add Copilot CLI hook configuration\"\ngit push\n```\n\nEn este momento, Copilot CLI puede detectar la configuración del enlace, aunque aún no haya creado los scripts de enlace.\n\n## 3. Agregar un banner de directiva al inicio de la sesión\n\nUse un `sessionStart` enlace para mostrar un banner cada vez que se inicia o reanuda una nueva Copilot CLI sesión. Esto deja claro a los desarrolladores que las directivas organizativas están activas.\n\nEl enlace `sessionStart` recibe información contextual, como el directorio de trabajo actual y la solicitud inicial. Cualquier output de este hook es ignorado por Copilot CLI, lo que lo hace adecuado para mensajes informativos.\n\n### Creación del script de banner de sesión (Bash)\n\nCree `.github/hooks/scripts/session-banner.sh`:\n\n```bash copy\n#!/bin/bash\nset -euo pipefail\n\ncat << 'EOF'\nCOPILOT CLI POLICY ACTIVE\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n• Prompts and tool use may be logged for auditing\n• High-risk commands may be blocked automatically\n• If something is blocked, follow the guidance shown\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\nEOF\nexit 0\n```\n\n### Creación del script de banner de sesión (PowerShell)\n\nCree `.github/hooks/scripts/session-banner.ps1`:\n\n```powershell copy\n$ErrorActionPreference = \"Stop\"\n\nWrite-Host @\"\nCOPILOT CLI POLICY ACTIVE\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n• Prompts and tool use may be logged for auditing\n• High-risk commands may be blocked automatically\n• If something is blocked, follow the guidance shown\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\"@\nexit 0\n```\n\n### Probar el banner de sesión\n\nPuede probar los scripts de banner directamente:\n\n```bash\n.github/hooks/scripts/session-banner.sh\n# or, for PowerShell\n.github/hooks/scripts/session-banner.ps1\n```\n\nAl ejecutar cualquiera de los scripts, debería ver el banner de directiva que se muestra en su terminal.\n\n## 4. Registrar las solicitudes para auditoría\n\nUse el `userPromptSubmitted` gancho para registrar cuando los usuarios envíen indicaciones a Copilot CLI. Este gancho se ejecuta cada vez que se envía un indicador, antes de invocar cualquier herramienta.\n\nEl enlace recibe una entrada JSON estructurada que incluye la marca de tiempo, el directorio de trabajo actual y el texto completo de la solicitud. La salida de este enlace se ignora.\n\n> \\[!IMPORTANT]\n> Las indicaciones pueden contener información confidencial. Aplique la redacción y siga las directivas de retención y manejo de datos de su organización al registrar estos datos.\n\n### Creación del script de registro de solicitudes (Bash)\n\nCree `.github/hooks/scripts/log-prompt.sh`:\n\n```bash copy\n#!/bin/bash\nset -euo pipefail\n\nINPUT=\"$(cat)\"\n\nTIMESTAMP_MS=\"$(echo \"$INPUT\" | jq -r '.timestamp // empty')\"\nCWD=\"$(echo \"$INPUT\" | jq -r '.cwd // empty')\"\n\n# This example logs only metadata, not the full prompt, to avoid storing\n# potentially sensitive data. Adjust to match your organization’s needs.\nLOG_DIR=\".github/hooks/logs\"\nmkdir -p \"$LOG_DIR\"\nchmod 700 \"$LOG_DIR\"\n\njq -n \\\n  --arg ts \"$TIMESTAMP_MS\" \\\n  --arg cwd \"$CWD\" \\\n  '{event:\"userPromptSubmitted\", timestampMs:$ts, cwd:$cwd}' \\\n  >> \"$LOG_DIR/audit.jsonl\"\n\nexit 0\n```\n\n### Crear el script de registro de comandos (PowerShell)\n\nCree `.github/hooks/scripts/log-prompt.ps1`:\n\n```powershell copy\n$ErrorActionPreference = \"Stop\"\n\n$inputObj = [Console]::In.ReadToEnd() | ConvertFrom-Json\n\n$timestampMs = $inputObj.timestamp\n$cwd = $inputObj.cwd\n$prompt = $inputObj.prompt\n\n# Optional example redaction. Adjust to match your organization’s needs.\n$redactedPrompt = $prompt -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]'\n\n$logDir = \".github/hooks/logs\"\nif (-not (Test-Path $logDir)) {\n  New-Item -ItemType Directory -Path $logDir -Force | Out-Null\n}\n\n$logEntry = @{\n  event       = \"userPromptSubmitted\"\n  timestampMs = $timestampMs\n  cwd         = $cwd\n  prompt      = $redactedPrompt\n} | ConvertTo-Json -Compress\n\nAdd-Content -Path \"$logDir/audit.jsonl\" -Value $logEntry\nexit 0\n```\n\n### Prueba del script de registro de solicitudes\n\nPuede probar los scripts directamente canalizando la entrada de ejemplo.\n\n```bash\necho '{\"timestamp\":1704614500000,\"cwd\":\"/repo\",\"prompt\":\"List all branches\"}' \\\n  | .github/hooks/scripts/log-prompt.sh\n# or, for PowerShell\necho '{\"timestamp\":1704614500000,\"cwd\":\"/repo\",\"prompt\":\"List all branches\"}' |\n  .github/hooks/scripts/log-prompt.ps1\n```\n\nDespués de ejecutar el script, compruebe `.github/hooks/logs/audit.jsonl` para ver una nueva entrada de registro.\n\n```bash copy\ncat .github/hooks/logs/audit.jsonl\n```\n\nEn este momento, las solicitudes enviadas a Copilot CLI en este repositorio se registran para la auditoría.\n\n## 5. Aplicar directivas con `preToolUse`\n\nUse el `preToolUse` gancho para evaluar una llamada de herramienta **antes de que se ejecute**. Este enlace puede permitir la ejecución (sin hacer nada) o denegar la ejecución (devolviendo una respuesta estructurada).\n\n### Comprenda la `preToolUse` entrada\n\nLa entrada del enlace `preToolUse` incluye:\n\n* `toolName`: la herramienta que Copilot CLI está a punto de ejecutarse (por ejemplo, `bash`)\n* `toolArgs`: **una cadena JSON** que contiene los argumentos de esa herramienta.\n\nDado que `toolArgs` es una cadena JSON, el script debe analizarlo antes de leer campos como `command`.\n\n> \\[!IMPORTANT]\n> Los argumentos y comandos de la herramienta pueden contener información confidencial, como tokens de API, contraseñas u otras credenciales. Aplique la redacción antes de registrar estos datos y siga las políticas de seguridad de su organización. Considere la posibilidad de registrar solo metadatos no confidenciales (nombre de herramienta, marca de tiempo, decisión de política) y dirigir eventos de auditoría a un sistema de registro centralizado protegido con los controles de acceso y políticas de retención adecuados.\n\n### Creación del script de directiva\n\nA continuación, cree un script de directiva. En este ejemplo:\n\n* Registra todos los intentos de uso de herramientas.\n* Aplica reglas de denegación solo a los comandos de Bash.\n* Bloquea patrones de alto riesgo, como la elevación de privilegios, las operaciones destructivas y los comandos de descarga y ejecución.\n\nPara permitir validar el flujo de denegación de forma segura, el script también incluye una regla de demostración temporal que bloquea un comando de prueba inofensivo. Después de confirmar que los enlaces funcionan según lo previsto, quite la regla de demostración y reemplácela por patrones que reflejen las directivas de la organización.\n\n#### Script de ejemplo (Bash)\n\nCree `.github/hooks/scripts/pre-tool-policy.sh`:\n\n```bash copy\n#!/bin/bash\nset -euo pipefail\n\nINPUT=\"$(cat)\"\n\nTOOL_NAME=\"$(echo \"$INPUT\" | jq -r '.toolName // empty')\"\nTOOL_ARGS_RAW=\"$(echo \"$INPUT\" | jq -r '.toolArgs // empty')\"  # JSON string\n\nLOG_DIR=\".github/hooks/logs\"\nmkdir -p \"$LOG_DIR\"\n\n# Example redaction logic.\n# GitHub does not currently provide built-in secret redaction for hooks.\n# This example shows one possible approach; many organizations prefer to\n# forward events to a centralized logging system that handles redaction.\n# Redact sensitive patterns before logging.\n# Adjust these patterns to match your organization's needs.\nREDACTED_TOOL_ARGS=\"$(echo \"$TOOL_ARGS_RAW\" | \\\n  sed -E 's/ghp_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \\\n  sed -E 's/gho_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \\\n  sed -E 's/ghu_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \\\n  sed -E 's/ghs_[A-Za-z0-9\\._\\-]{20,}/[REDACTED_TOKEN]/g' | \\\n  sed -E 's/Bearer [A-Za-z0-9_\\-\\.]+/Bearer [REDACTED]/g' | \\\n  sed -E 's/--password[= ][^ ]+/--password=[REDACTED]/g' | \\\n  sed -E 's/--token[= ][^ ]+/--token=[REDACTED]/g')\"\n\n# Log attempted tool use with redacted toolArgs.\njq -n \\\n  --arg tool \"$TOOL_NAME\" \\\n  --arg toolArgs \"$REDACTED_TOOL_ARGS\" \\\n  '{event:\"preToolUse\", toolName:$tool, toolArgs:$toolArgs}' \\\n  >> \"$LOG_DIR/audit.jsonl\"\n\n# Only enforce command rules for bash.\nif [ \"$TOOL_NAME\" != \"bash\" ]; then\n  exit 0\nfi\n\n# Parse toolArgs JSON string.\n# If toolArgs isn't valid JSON for some reason, allow (and rely on logs).\nif ! echo \"$TOOL_ARGS_RAW\" | jq -e . >/dev/null 2>&1; then\n  exit 0\nfi\n\nCOMMAND=\"$(echo \"$TOOL_ARGS_RAW\" | jq -r '.command // empty')\"\n\n# ---------------------------------------------------------------------------\n# Demo-only deny rule for safe testing.\n# This blocks a harmless test command so you can validate the deny flow.\n# Remove this rule after confirming your hooks work as expected.\n# ---------------------------------------------------------------------------\nif echo \"$COMMAND\" | grep -q \"COPILOT_HOOKS_DENY_DEMO\"; then\n  deny \"Blocked demo command (test rule). Remove this rule after validating hooks.\"\nfi\n\ndeny() {\n  local reason=\"$1\"\n\n  # Redact sensitive patterns from command before logging.\n  local redacted_cmd=\"$(echo \"$COMMAND\" | \\\n    sed -E 's/ghp_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \\\n    sed -E 's/gho_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \\\n    sed -E 's/ghu_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \\\n    sed -E 's/ghs_[A-Za-z0-9\\.\\-_]{20,}/[REDACTED_TOKEN]/g' | \\\n    sed -E 's/Bearer [A-Za-z0-9_\\-\\.]+/Bearer [REDACTED]/g' | \\\n    sed -E 's/--password[= ][^ ]+/--password=[REDACTED]/g' | \\\n    sed -E 's/--token[= ][^ ]+/--token=[REDACTED]/g')\"\n\n  # Log the denial decision with redacted command.\n  jq -n \\\n    --arg cmd \"$redacted_cmd\" \\\n    --arg r \"$reason\" \\\n    '{event:\"policyDeny\", toolName:\"bash\", command:$cmd, reason:$r}' \\\n    >> \"$LOG_DIR/audit.jsonl\"\n\n  # Return a denial response.\n  jq -n \\\n    --arg r \"$reason\" \\\n    '{permissionDecision:\"deny\", permissionDecisionReason:$r}'\n\n  exit 0\n}\n\n# Privilege escalation\nif echo \"$COMMAND\" | grep -qE '\\b(sudo|su|runas)\\b'; then\n  deny \"Privilege escalation requires manual approval.\"\nfi\n\n# Destructive filesystem operations targeting root\nif echo \"$COMMAND\" | grep -qE 'rm\\s+-rf\\s*/($|\\s)|rm\\s+.*-rf\\s*/($|\\s)'; then\n  deny \"Destructive operations targeting the filesystem root require manual approval.\"\nfi\n\n# System-level destructive operations\nif echo \"$COMMAND\" | grep -qE '\\b(mkfs|dd|format)\\b'; then\n  deny \"System-level destructive operations are not allowed via automated execution.\"\nfi\n\n# Download-and-execute patterns\nif echo \"$COMMAND\" | grep -qE 'curl.*\\|\\s*(bash|sh)|wget.*\\|\\s*(bash|sh)'; then\n  deny \"Download-and-execute patterns require manual approval.\"\nfi\n\n# Allow by default\nexit 0\n```\n\n#### Creación del script de directiva (PowerShell)\n\nCree `.github/hooks/scripts/pre-tool-policy.ps1`:\n\n```powershell copy\n$ErrorActionPreference = \"Stop\"\n\n$inputObj = [Console]::In.ReadToEnd() | ConvertFrom-Json\n$toolName = $inputObj.toolName\n$toolArgsRaw = $inputObj.toolArgs  # JSON string\n\n$logDir = \".github/hooks/logs\"\nif (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }\n\n# Example redaction logic.\n# GitHub does not currently provide built-in secret redaction for hooks.\n# This example shows one possible approach; many organizations prefer to\n# forward events to a centralized logging system that handles redaction.\n# Redact sensitive patterns before logging.\n# Adjust these patterns to match your organization's needs.\n$redactedToolArgs = $toolArgsRaw `\n  -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `\n  -replace 'gho_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `\n  -replace 'ghu_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `\n  -replace 'ghs_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `\n  -replace 'Bearer [A-Za-z0-9_\\-\\.]+', 'Bearer [REDACTED]' `\n  -replace '--password[= ][^ ]+', '--password=[REDACTED]' `\n  -replace '--token[= ][^ ]+', '--token=[REDACTED]'\n\n# Log attempted tool use with redacted toolArgs.\n(@{\n  event    = \"preToolUse\"\n  toolName = $toolName\n  toolArgs = $redactedToolArgs\n} | ConvertTo-Json -Compress) | Add-Content -Path \"$logDir/audit.jsonl\"\n\nif ($toolName -ne \"bash\") { exit 0 }\n\n# Parse toolArgs JSON string.\n$toolArgs = $null\ntry { $toolArgs = $toolArgsRaw | ConvertFrom-Json } catch { exit 0 }\n\n$command = $toolArgs.command\n\n# ---------------------------------------------------------------------------\n# Demo-only deny rule for safe testing.\n# This blocks a harmless test command so you can validate the deny flow.\n# Remove this rule after confirming your hooks work as expected.\n# ---------------------------------------------------------------------------\nif ($command -match 'COPILOT_HOOKS_DENY_DEMO') {\n  Deny \"Blocked demo command (test rule). Remove this rule after validating hooks.\"\n}\n\nfunction Deny([string]$reason) {\n  # Redact sensitive patterns from command before logging.\n  $redactedCommand = $command `\n    -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `\n    -replace 'gho_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `\n    -replace 'ghu_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `\n    -replace 'ghs_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `\n    -replace 'Bearer [A-Za-z0-9_\\-\\.]+', 'Bearer [REDACTED]' `\n    -replace '--password[= ][^ ]+', '--password=[REDACTED]' `\n    -replace '--token[= ][^ ]+', '--token=[REDACTED]'\n\n  # Log the denial decision with redacted command.\n  (@{\n    event    = \"policyDeny\"\n    toolName = \"bash\"\n    command  = $redactedCommand\n    reason   = $reason\n  } | ConvertTo-Json -Compress) | Add-Content -Path \"$logDir/audit.jsonl\"\n\n  (@{\n    permissionDecision = \"deny\"\n    permissionDecisionReason = $reason\n  } | ConvertTo-Json -Compress)\n\n  exit 0\n}\n\nif ($command -match '\\b(sudo|su|runas)\\b') { Deny \"Privilege escalation requires manual approval.\" }\nif ($command -match 'rm\\s+-rf\\s*/(\\s|$)|rm\\s+.*-rf\\s*/(\\s|$)') { Deny \"Destructive operations targeting the filesystem root require manual approval.\" }\nif ($command -match '\\b(mkfs|dd|format)\\b') { Deny \"System-level destructive operations are not allowed via automated execution.\" }\nif ($command -match 'curl.*\\|\\s*(bash|sh)|wget.*\\|\\s*(bash|sh)') { Deny \"Download-and-execute patterns require manual approval.\" }\n\nexit 0\n```\n\n### Prueba del script de directiva\n\nPuede probar los scripts canalizando la entrada de ejemplo `preToolUse`.\n\nPermitir ejemplo:\n\n```bash\necho '{\"toolName\":\"bash\",\"toolArgs\":\"{\\\"command\\\":\\\"git status\\\"}\"}' \\\n  | .github/hooks/scripts/pre-tool-policy.sh\n# or, for PowerShell\necho '{\"toolName\":\"bash\",\"toolArgs\":\"{\\\"command\\\":\\\"git status\\\"}\"}' |\n  .github/hooks/scripts/pre-tool-policy.ps1\n```\n\nEjemplo de denegación:\n\n```bash\necho '{\"toolName\":\"bash\",\"toolArgs\":\"{\\\"command\\\":\\\"sudo rm -rf /\\\"}\"}' \\\n  | .github/hooks/scripts/pre-tool-policy.sh\n# or, for PowerShell\necho '{\"toolName\":\"bash\",\"toolArgs\":\"{\\\"command\\\":\\\"sudo rm -rf /\\\"}\"}' |\n  .github/hooks/scripts/pre-tool-policy.ps1\n```\n\nDespués de ejecutar el ejemplo de denegación, compruebe `.github/hooks/logs/audit.jsonl` para obtener una nueva entrada de registro de denegación.\n\n```json\n{\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Privilege escalation requires manual approval.\"}\n```\n\nEn este momento, los comandos de alto riesgo `bash` se bloquean para la ejecución automática en este repositorio.\n\n## 6. Prueba de un extremo a otro en el repositorio\n\nUna vez que hayas creado el archivo de configuración y los scripts, comprueba que los hooks funcionan como se espera cuando usas Copilot CLI en este repositorio.\n\n### Valida tu archivo de configuración de hook\n\nCompruebe que el archivo de configuración de enlace sea json válido:\n\n```bash copy\njq '.' < .github/hooks/copilot-cli-policy.json\n```\n\n### Comprobación de los permisos de script (sistemas basados en Unix)\n\nEn macOS y Linux, confirme que los scripts de Bash son ejecutables:\n\n```bash copy\nchmod +x .github/hooks/scripts/*.sh\n```\n\n### Ejecución de una sesión básica\n\nInicie una nueva Copilot CLI sesión en el repositorio:\n\n```bash copy\ncopilot -p \"Show me the status of this repository\"\n```\n\nResultados esperados:\n\n* Ves el banner de política (de `sessionStart`).\n* Se agrega una nueva entrada a `.github/hooks/logs/audit.jsonl` (desde `userPromptSubmitted`).\n\n### Uso de la herramienta de desencadenamiento y verificación del registro\n\nEjecuta un aviso que haga que Copilot CLI use una herramienta (por ejemplo, Bash):\n\n```bash copy\ncopilot -p \"Show me the last 5 git commits\"\n```\n\nResultados esperados:\n\n* Se agrega una entrada `preToolUse` a `.github/hooks/logs/audit.jsonl`.\n* Si se permite la llamada a la herramienta, la ejecución continúa normalmente.\n\n### Prueba de un comando denegado\n\nEl script de directiva de ejemplo incluye una regla de demostración temporal que bloquea los comandos que contienen la cadena `COPILOT_HOOKS_DENY_DEMO`. Esto le permite validar el flujo de denegación de forma segura sin ejecutar comandos destructivos.\n\nEjecute un mensaje que provocaría un comando denegado:\n\n```bash copy\ncopilot -p \"Run a test command: echo COPILOT_HOOKS_DENY_DEMO\"\n```\n\nResultados esperados:\n\n* Copilot CLI no ejecuta el comando .\n* El enlace devuelve una respuesta de denegación con un motivo claro.\n* Se escribe una entrada `policyDeny` en `.github/hooks/logs/audit.jsonl`.\n\nDespués de confirmar que el flujo de denegación funciona correctamente, quite la regla de demostración del script y reemplácela por patrones de denegación que reflejen las directivas de la organización.\n\n### Inspección de los registros de auditoría\n\nPara ver las entradas recientes:\n\n```bash copy\ntail -n 50 .github/hooks/logs/audit.jsonl\n```\n\nPara filtrar solo las decisiones denegadas:\n\n```bash copy\njq 'select(.event==\"policyDeny\")' .github/hooks/logs/audit.jsonl\n```\n\n## 7. Implementar de forma segura en todos los equipos\n\nDespués de validar los enlaces en un único repositorio, impleméntelos gradualmente para evitar interrumpir los flujos de trabajo de desarrollo.\n\n### Elección de una estrategia de lanzamiento\n\nEntre los enfoques comunes de lanzamiento se incluyen:\n\n* **Despliegue centrado en el registro (recomendado)**: empiece por registrar las solicitudes y el uso de la herramienta sin denegar la ejecución. Revise los registros durante un período de tiempo y, a continuación, introduzca reglas de denegación una vez que comprenda los patrones de uso comunes.\n* **Despliegue por equipos**: implemente enlaces en un equipo o repositorio a la vez, recopile comentarios y expanda a equipos adicionales.\n* **Implementación basada en** riesgos: comience con repositorios que controlan sistemas confidenciales o infraestructura de producción y, a continuación, expanda a repositorios de menor riesgo.\n\n### Comunicar expectativas\n\nAntes de aplicar reglas de denegación, asegúrese de que los desarrolladores comprendan lo siguiente:\n\n* Esos enlaces están activos en el repositorio\n* Qué tipos de comandos se pueden bloquear\n* Procedimiento para continuar si se deniega un comando\n\nLa comunicación clara reduce la confusión y las solicitudes de soporte técnico.\n\n### Mantener las políticas mantenibles\n\nA medida que evoluciona el uso:\n\n* Almacene la configuración del enlace y los scripts en el control de versiones.\n* Revise los registros de auditoría periódicamente para detectar nuevos patrones de riesgo.\n* Actualice las reglas de denegación incrementalmente en lugar de agregar coincidencias amplias.\n* Documente por qué existe cada regla de denegación, especialmente para las restricciones de alto impacto.\n\n### Maneja las excepciones con cuidado\n\nAlgunos equipos (por ejemplo, los equipos de infraestructura o plataforma) pueden requerir permisos más amplios. Para controlar esto de forma segura:\n\n* Mantenga configuraciones de enlace independientes para distintos repositorios.\n* Mantenga las excepciones estrechas y bien documentadas.\n* Evite los desvíos locales ad hoc que minan la capacidad de auditoría.\n\n## Lectura adicional\n\nPara resolver problemas de ganchos, consulte [Personalización de flujos de trabajo de agente con enlaces](/es/copilot/how-tos/copilot-on-github/customize-copilot/customize-cloud-agent/use-hooks#troubleshooting)."}