Skip to main content

Utilisation de hooks avec Copilot CLI pour une exécution prévisible et conforme aux stratégies

Utilisez des hooks pour consigner les invites utilisateur et contrôler quels outils Copilot CLI peuvent s’exécuter dans un référentiel, afin que les équipes puissent automatiser en toute sécurité tout en respectant les exigences de sécurité et de conformité de votre organisation.

Ce tutoriel est destiné aux ingénieurs DevOps, aux équipes de plateforme et aux responsables de l’ingénierie qui prennent en charge les développeurs à l’aide de Copilot CLI.

Les hooks sont des scripts personnalisés qui s’exécutent à des points spécifiques pendant une session Copilot CLI. Ils peuvent inspecter les invites et les appels d’outils, consigner des informations pour l’audit et même bloquer l’exécution de certaines commandes.

Vous allez configurer des hooks au niveau du référentiel qui :

  • Assurez la visibilité sur les messages et l’utilisation des outils.
  • Bloquer les modèles de commandes à haut risque avant l’exécution.
  • Aidez les développeurs à comprendre les stratégies organisationnelles avec une messagerie claire.

Prerequisites

  • Connaissance des scripts d’interpréteur de commandes (Bash ou PowerShell)
  • Compréhension de base des fichiers de configuration JSON
  • Accès à un référentiel dans lequel Copilot CLI est utilisé
  •         `jq` installé (pour les exemples Bash)
    

1. Définir une stratégie d’organisation

Avant d’écrire des scripts de hook, décidez quelles actions doivent être autorisées automatiquement et qui doivent nécessiter une révision humaine.

Une stratégie claire vous permet d’éviter le sur-blocage tout en réduisant les risques.

Identifier les commandes qui nécessitent toujours une révision

Commencez par identifier les modèles qui ne doivent jamais être exécutés automatiquement par Copilot CLI. Voici quelques exemples courants :

  •         **Escalade de privilèges** : `sudo`, `su`, `runas`
    
  •         **Opérations système destructrices** : `rm -rf /`, `mkfs`, `dd`, `format`
    
  •         **Modèles de téléchargement et d’exécution** : `curl ... | bash`, `wget ... | sh`, PowerShell `iex (irm ...)`
    

Ces commandes peuvent avoir des effets irréversibles s’ils sont exécutés involontairement.

Décider de ce qu’il faut consigner

Lorsque vous utilisez des hooks, vous pouvez capturer des informations sur la façon dont Copilot CLI est utilisé dans un référentiel, y compris les invites envoyées par les utilisateurs et les outils que Copilot CLI tente d’exécuter.

Au minimum, la plupart des organisations journalisent :

  • Le horodatage et le chemin d’accès du référentiel
  • Texte de l'invite (ou forme réduite)
  • Nom de l’outil et arguments de l’outil
  • Toute décision de stratégie (par exemple, une commande refusée et sa raison)

Évitez de journaliser les secrets ou les informations d’identification. Si des invites ou des commandes peuvent contenir des données sensibles, appliquez le masquage avant d’écrire dans les logs.

Ce tutoriel utilise un répertoire local .github/hooks/logs comme exemple simple et illustrant. Ces fichiers journaux ne sont pas destinés à être intégrés au référentiel et ne résident généralement que sur l’ordinateur d’un développeur.

Dans les environnements de production, de nombreuses organisations transfèrent les événements de hook vers un système centralisé de journalisation ou d’observabilité plutôt que de rédiger des journaux localement. Cela permet aux équipes d’appliquer la rédaction cohérente, les contrôles d’accès, les stratégies de rétention et la surveillance entre les référentiels et les utilisateurs.

S'aligner sur les parties prenantes

Avant d’appliquer des stratégies, passez en revue les éléments suivants :

  • Équipes de sécurité ou de conformité pour confirmer les limites des risques
  • Équipes de plateforme ou d’infrastructure, qui peuvent avoir besoin d’autorisations plus larges
  • Les équipes de développement, de sorte qu’elles comprennent ce qui sera bloqué et pourquoi

Les attentes claires facilitent l’adoption et la maintenance des stratégies.

2. Configurer des fichiers de hooks du référentiel

Tout au long de ce tutoriel, vous allez utiliser hooks à portée de référentiel stockés dans le référentiel sous .github/hooks/. Ces hooks s’appliquent chaque fois que Copilot CLI s’exécute à partir de ce référentiel.

Remarque

Copilot les agents chargent les fichiers de configuration du hook depuis le .github/hooks/*.json du référentiel. Les hooks s’exécutent de manière synchrone et peuvent bloquer l’exécution.

Créer la structure de répertoires

À partir de la racine du référentiel, créez des répertoires pour votre configuration de hook, vos scripts et vos journaux :

Bash
mkdir -p .github/hooks/scripts
mkdir -p .github/hooks/logs

Ajoutez .github/hooks/logs/ à .gitignore pour que les journaux d’audit locaux ne soient pas intégrés dans le dépôt :

Bash
echo ".github/hooks/logs/" >> .gitignore

Ce tutoriel utilise la structure suivante :

.github/
└── hooks/
    ├── copilot-cli-policy.json
    ├── logs/
    │   └── audit.jsonl
    └── scripts/
        ├── session-banner.sh
        ├── session-banner.ps1
        ├── log-prompt.sh
        ├── log-prompt.ps1
        ├── pre-tool-policy.sh
        └── pre-tool-policy.ps1

Créer un fichier de configuration de hook

Créez un fichier de configuration de hook à l’adresse .github/hooks/copilot-cli-policy.json.

Ce fichier définit les hooks qui s’exécutent, lorsqu’ils s’exécutent et les scripts qu’ils exécutent.

JSON
{
  "version": 1,
  "hooks": {
    "sessionStart": [
      {
        "type": "command",
        "bash": "./scripts/session-banner.sh",
        "powershell": "./scripts/session-banner.ps1",
        "cwd": ".github/hooks",
        "timeoutSec": 10
      }
    ],
    "userPromptSubmitted": [
      {
        "type": "command",
        "bash": "./scripts/log-prompt.sh",
        "powershell": "./scripts/log-prompt.ps1",
        "cwd": ".github/hooks",
        "timeoutSec": 10
      }
    ],
    "preToolUse": [
      {
        "type": "command",
        "bash": "./scripts/pre-tool-policy.sh",
        "powershell": "./scripts/pre-tool-policy.ps1",
        "cwd": ".github/hooks",
        "timeoutSec": 15
      }
    ]
  }
}

Comprendre ce que fait cette configuration

Cette configuration configure trois hooks :

  •         `sessionStart`: affiche un message d’information quand une nouvelle session d’agent démarre ou reprend.
    
  •         `userPromptSubmitted`: s’exécute chaque fois qu’un utilisateur envoie une commande.
    
  •         `preToolUse`: s’exécute avant l’exécution d’un outil et peut autoriser ou refuser explicitement l’exécution.
    

Valider et partager la configuration du hook

Lorsque vous êtes prêt à partager la configuration du hook avec des collaborateurs (par exemple, via une pull request ou dans un référentiel de test), validez la configuration du hook et les scripts. Ne validez aucun journal d’audit local.

Bash
git add .github/hooks/copilot-cli-policy.json .github/hooks/scripts
git commit -m "Add Copilot CLI hook configuration"
git push

À ce stade, Copilot CLI peut découvrir votre configuration de hook, même si vous n’avez pas encore créé les scripts de hook.

3. Ajouter une bannière de stratégie au démarrage de la session

Pour afficher une bannière chaque fois qu'une nouvelle session de Copilot CLI commence ou reprend, utilisez un crochet sessionStart. Cela indique clairement aux développeurs que les stratégies organisationnelles sont actives.

Le sessionStart hook reçoit des informations contextuelles telles que le répertoire de travail actuel et l’invite initiale. Toute sortie de ce hook est ignorée par Copilot CLI, ce qui le rend adapté aux messages informationnels.

Créer le script de bannière de session (Bash)

Créer .github/hooks/scripts/session-banner.sh:

Bash
#!/bin/bash
set -euo pipefail

cat << 'EOF'
COPILOT CLI POLICY ACTIVE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• Prompts and tool use may be logged for auditing
• High-risk commands may be blocked automatically
• If something is blocked, follow the guidance shown
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EOF
exit 0

Créer le script de bannière de session (PowerShell)

Créer .github/hooks/scripts/session-banner.ps1:

PowerShell
$ErrorActionPreference = "Stop"

Write-Host @"
COPILOT CLI POLICY ACTIVE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• Prompts and tool use may be logged for auditing
• High-risk commands may be blocked automatically
• If something is blocked, follow the guidance shown
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"@
exit 0

Tester la bannière de session

Vous pouvez tester directement les scripts de bannière :

.github/hooks/scripts/session-banner.sh
# or, for PowerShell
.github/hooks/scripts/session-banner.ps1

Lorsque vous exécutez l’un ou l’autre script, vous devez voir la bannière de stratégie affichée dans votre terminal.

4. Messages de journalisation pour l’audit

Utilisez le hook userPromptSubmitted pour enregistrer quand les utilisateurs envoient des requêtes à Copilot CLI. Ce hook s’exécute chaque fois qu’une invite est envoyée, avant qu’aucun outil ne soit appelé.

Le hook reçoit une entrée JSON structurée qui inclut l’horodatage, le répertoire de travail actif et le texte d’invite complet. La sortie de ce hook est ignorée.

Important

Les sujets peuvent contenir des informations sensibles. Appliquez la rédaction et suivez les stratégies de gestion et de rétention des données de votre organisation lors de la journalisation de ces données.

Créer le script de journalisation du terminal (Bash)

Créer .github/hooks/scripts/log-prompt.sh:

Bash
#!/bin/bash
set -euo pipefail

INPUT="$(cat)"

TIMESTAMP_MS="$(echo "$INPUT" | jq -r '.timestamp // empty')"
CWD="$(echo "$INPUT" | jq -r '.cwd // empty')"

# This example logs only metadata, not the full prompt, to avoid storing
# potentially sensitive data. Adjust to match your organization’s needs.
LOG_DIR=".github/hooks/logs"
mkdir -p "$LOG_DIR"
chmod 700 "$LOG_DIR"

jq -n \
  --arg ts "$TIMESTAMP_MS" \
  --arg cwd "$CWD" \
  '{event:"userPromptSubmitted", timestampMs:$ts, cwd:$cwd}' \
  >> "$LOG_DIR/audit.jsonl"

exit 0

Créer le script de journalisation d’invite de commandes (PowerShell)

Créer .github/hooks/scripts/log-prompt.ps1:

PowerShell
$ErrorActionPreference = "Stop"

$inputObj = [Console]::In.ReadToEnd() | ConvertFrom-Json

$timestampMs = $inputObj.timestamp
$cwd = $inputObj.cwd
$prompt = $inputObj.prompt

# Optional example redaction. Adjust to match your organization’s needs.
$redactedPrompt = $prompt -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]'

$logDir = ".github/hooks/logs"
if (-not (Test-Path $logDir)) {
  New-Item -ItemType Directory -Path $logDir -Force | Out-Null
}

$logEntry = @{
  event       = "userPromptSubmitted"
  timestampMs = $timestampMs
  cwd         = $cwd
  prompt      = $redactedPrompt
} | ConvertTo-Json -Compress

Add-Content -Path "$logDir/audit.jsonl" -Value $logEntry
exit 0

Tester le script de journalisation de l'invite de commande

Vous pouvez tester les scripts directement en redirigeant un exemple d'entrée.

echo '{"timestamp":1704614500000,"cwd":"/repo","prompt":"List all branches"}' \
  | .github/hooks/scripts/log-prompt.sh
# or, for PowerShell
echo '{"timestamp":1704614500000,"cwd":"/repo","prompt":"List all branches"}' |
  .github/hooks/scripts/log-prompt.ps1

Après avoir exécuté le script, recherchez .github/hooks/logs/audit.jsonl pour une nouvelle entrée de journal.

Bash
cat .github/hooks/logs/audit.jsonl

À ce stade, les invites envoyées à Copilot CLI dans ce référentiel sont enregistrées à des fins d'audit.

5. Appliquer des stratégies avec preToolUse

Utilisez le preToolUse hook pour évaluer un appel d’outil avant son exécution. Ce hook peut autoriser l’exécution (en ne faisant rien) ou refuser l’exécution (en retournant une réponse structurée).

Comprendre l’entrée preToolUse

L’entrée preToolUse de hook comprend les éléments suivants :

  •         `toolName` : l'outil que Copilot CLI va bientôt exécuter (par exemple, `bash`)
    
  •         `toolArgs`: **chaîne JSON** contenant les arguments de cet outil
    

Étant donné qu’il toolArgs s’agit d’une chaîne JSON, votre script doit l’analyser avant de lire des champs comme command.

Important

Les arguments et commandes de l’outil peuvent contenir des informations sensibles telles que des jetons d’API, des mots de passe ou d’autres informations d’identification. Appliquez la rédaction avant de journaliser ces données et suivez les stratégies de sécurité de votre organisation. Envisagez de journaliser uniquement les métadonnées non sensibles (nom de l’outil, horodatage, décision de stratégie) et de diriger les événements d’audit vers un système de journalisation sécurisé et centralisé avec des contrôles d’accès et des stratégies de rétention appropriés.

Créer le script de stratégie

Ensuite, créez un script de stratégie. Cet exemple :

  • Enregistre toutes les tentatives d’utilisation de l’outil.
  • Applique des règles de refus uniquement aux commandes bash.
  • Bloque les modèles à haut risque tels que l’escalade de privilèges, les opérations destructrices et les commandes download-and-execute.

Pour vous permettre de valider le flux de refus en toute sécurité, le script inclut également une règle de démonstration temporaire qui bloque une commande de test inoffensive. Après avoir confirmé que les hooks fonctionnent comme prévu, supprimez la règle de démonstration et remplacez-la par des modèles qui reflètent les stratégies de votre organisation.

Exemple de script (Bash)

Créer .github/hooks/scripts/pre-tool-policy.sh:

Bash
#!/bin/bash
set -euo pipefail

INPUT="$(cat)"

TOOL_NAME="$(echo "$INPUT" | jq -r '.toolName // empty')"
TOOL_ARGS_RAW="$(echo "$INPUT" | jq -r '.toolArgs // empty')"  # JSON string

LOG_DIR=".github/hooks/logs"
mkdir -p "$LOG_DIR"

# Example redaction logic.
# GitHub does not currently provide built-in secret redaction for hooks.
# This example shows one possible approach; many organizations prefer to
# forward events to a centralized logging system that handles redaction.
# Redact sensitive patterns before logging.
# Adjust these patterns to match your organization's needs.
REDACTED_TOOL_ARGS="$(echo "$TOOL_ARGS_RAW" | \
  sed -E 's/ghp_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
  sed -E 's/gho_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
  sed -E 's/ghu_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
  sed -E 's/ghs_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
  sed -E 's/Bearer [A-Za-z0-9_\-\.]+/Bearer [REDACTED]/g' | \
  sed -E 's/--password[= ][^ ]+/--password=[REDACTED]/g' | \
  sed -E 's/--token[= ][^ ]+/--token=[REDACTED]/g')"

# Log attempted tool use with redacted toolArgs.
jq -n \
  --arg tool "$TOOL_NAME" \
  --arg toolArgs "$REDACTED_TOOL_ARGS" \
  '{event:"preToolUse", toolName:$tool, toolArgs:$toolArgs}' \
  >> "$LOG_DIR/audit.jsonl"

# Only enforce command rules for bash.
if [ "$TOOL_NAME" != "bash" ]; then
  exit 0
fi

# Parse toolArgs JSON string.
# If toolArgs isn't valid JSON for some reason, allow (and rely on logs).
if ! echo "$TOOL_ARGS_RAW" | jq -e . >/dev/null 2>&1; then
  exit 0
fi

COMMAND="$(echo "$TOOL_ARGS_RAW" | jq -r '.command // empty')"

# ---------------------------------------------------------------------------
# Demo-only deny rule for safe testing.
# This blocks a harmless test command so you can validate the deny flow.
# Remove this rule after confirming your hooks work as expected.
# ---------------------------------------------------------------------------
if echo "$COMMAND" | grep -q "COPILOT_HOOKS_DENY_DEMO"; then
  deny "Blocked demo command (test rule). Remove this rule after validating hooks."
fi

deny() {
  local reason="$1"

  # Redact sensitive patterns from command before logging.
  local redacted_cmd="$(echo "$COMMAND" | \
    sed -E 's/ghp_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
    sed -E 's/gho_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
    sed -E 's/ghu_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
    sed -E 's/ghs_[A-Za-z0-9]{20,}/[REDACTED_TOKEN]/g' | \
    sed -E 's/Bearer [A-Za-z0-9_\-\.]+/Bearer [REDACTED]/g' | \
    sed -E 's/--password[= ][^ ]+/--password=[REDACTED]/g' | \
    sed -E 's/--token[= ][^ ]+/--token=[REDACTED]/g')"

  # Log the denial decision with redacted command.
  jq -n \
    --arg cmd "$redacted_cmd" \
    --arg r "$reason" \
    '{event:"policyDeny", toolName:"bash", command:$cmd, reason:$r}' \
    >> "$LOG_DIR/audit.jsonl"

  # Return a denial response.
  jq -n \
    --arg r "$reason" \
    '{permissionDecision:"deny", permissionDecisionReason:$r}'

  exit 0
}

# Privilege escalation
if echo "$COMMAND" | grep -qE '\b(sudo|su|runas)\b'; then
  deny "Privilege escalation requires manual approval."
fi

# Destructive filesystem operations targeting root
if echo "$COMMAND" | grep -qE 'rm\s+-rf\s*/($|\s)|rm\s+.*-rf\s*/($|\s)'; then
  deny "Destructive operations targeting the filesystem root require manual approval."
fi

# System-level destructive operations
if echo "$COMMAND" | grep -qE '\b(mkfs|dd|format)\b'; then
  deny "System-level destructive operations are not allowed via automated execution."
fi

# Download-and-execute patterns
if echo "$COMMAND" | grep -qE 'curl.*\|\s*(bash|sh)|wget.*\|\s*(bash|sh)'; then
  deny "Download-and-execute patterns require manual approval."
fi

# Allow by default
exit 0

Créer le script de stratégie (PowerShell)

Créer .github/hooks/scripts/pre-tool-policy.ps1:

PowerShell
$ErrorActionPreference = "Stop"

$inputObj = [Console]::In.ReadToEnd() | ConvertFrom-Json
$toolName = $inputObj.toolName
$toolArgsRaw = $inputObj.toolArgs  # JSON string

$logDir = ".github/hooks/logs"
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }

# Example redaction logic.
# GitHub does not currently provide built-in secret redaction for hooks.
# This example shows one possible approach; many organizations prefer to
# forward events to a centralized logging system that handles redaction.
# Redact sensitive patterns before logging.
# Adjust these patterns to match your organization's needs.
$redactedToolArgs = $toolArgsRaw `
  -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
  -replace 'gho_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
  -replace 'ghu_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
  -replace 'ghs_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
  -replace 'Bearer [A-Za-z0-9_\-\.]+', 'Bearer [REDACTED]' `
  -replace '--password[= ][^ ]+', '--password=[REDACTED]' `
  -replace '--token[= ][^ ]+', '--token=[REDACTED]'

# Log attempted tool use with redacted toolArgs.
(@{
  event    = "preToolUse"
  toolName = $toolName
  toolArgs = $redactedToolArgs
} | ConvertTo-Json -Compress) | Add-Content -Path "$logDir/audit.jsonl"

if ($toolName -ne "bash") { exit 0 }

# Parse toolArgs JSON string.
$toolArgs = $null
try { $toolArgs = $toolArgsRaw | ConvertFrom-Json } catch { exit 0 }

$command = $toolArgs.command

# ---------------------------------------------------------------------------
# Demo-only deny rule for safe testing.
# This blocks a harmless test command so you can validate the deny flow.
# Remove this rule after confirming your hooks work as expected.
# ---------------------------------------------------------------------------
if ($command -match 'COPILOT_HOOKS_DENY_DEMO') {
  Deny "Blocked demo command (test rule). Remove this rule after validating hooks."
}

function Deny([string]$reason) {
  # Redact sensitive patterns from command before logging.
  $redactedCommand = $command `
    -replace 'ghp_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
    -replace 'gho_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
    -replace 'ghu_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
    -replace 'ghs_[A-Za-z0-9]{20,}', '[REDACTED_TOKEN]' `
    -replace 'Bearer [A-Za-z0-9_\-\.]+', 'Bearer [REDACTED]' `
    -replace '--password[= ][^ ]+', '--password=[REDACTED]' `
    -replace '--token[= ][^ ]+', '--token=[REDACTED]'

  # Log the denial decision with redacted command.
  (@{
    event    = "policyDeny"
    toolName = "bash"
    command  = $redactedCommand
    reason   = $reason
  } | ConvertTo-Json -Compress) | Add-Content -Path "$logDir/audit.jsonl"

  (@{
    permissionDecision = "deny"
    permissionDecisionReason = $reason
  } | ConvertTo-Json -Compress)

  exit 0
}

if ($command -match '\b(sudo|su|runas)\b') { Deny "Privilege escalation requires manual approval." }
if ($command -match 'rm\s+-rf\s*/(\s|$)|rm\s+.*-rf\s*/(\s|$)') { Deny "Destructive operations targeting the filesystem root require manual approval." }
if ($command -match '\b(mkfs|dd|format)\b') { Deny "System-level destructive operations are not allowed via automated execution." }
if ($command -match 'curl.*\|\s*(bash|sh)|wget.*\|\s*(bash|sh)') { Deny "Download-and-execute patterns require manual approval." }

exit 0

Tester le script de stratégie

Vous pouvez tester les scripts en pipant des exemples preToolUse d’entrée.

Autoriser l'exemple :

echo '{"toolName":"bash","toolArgs":"{\"command\":\"git status\"}"}' \
  | .github/hooks/scripts/pre-tool-policy.sh
# or, for PowerShell
echo '{"toolName":"bash","toolArgs":"{\"command\":\"git status\"}"}' |
  .github/hooks/scripts/pre-tool-policy.ps1

Exemple de refus :

echo '{"toolName":"bash","toolArgs":"{\"command\":\"sudo rm -rf /\"}"}' \
  | .github/hooks/scripts/pre-tool-policy.sh
# or, for PowerShell
echo '{"toolName":"bash","toolArgs":"{\"command\":\"sudo rm -rf /\"}"}' |
  .github/hooks/scripts/pre-tool-policy.ps1

Après avoir exécuté l’exemple de refus, recherchez pour une nouvelle entrée de journal de refus dans .github/hooks/logs/audit.jsonl.

{"permissionDecision":"deny","permissionDecisionReason":"Privilege escalation requires manual approval."}

À ce stade, les commandes à haut risque bash sont bloquées contre l’exécution automatique dans ce référentiel.

6. Tester de bout en bout dans le référentiel

Une fois que vous avez créé le fichier de configuration et les scripts, vérifiez que les hooks s’exécutent comme prévu lorsque vous utilisez Copilot CLI dans ce référentiel.

Valider votre fichier de configuration de hook

Vérifiez que votre fichier de configuration de hook est valide JSON :

Bash
jq '.' < .github/hooks/copilot-cli-policy.json

Vérifier les autorisations de script (systèmes unix)

Sur macOS et Linux, vérifiez que vos scripts Bash sont exécutables :

Bash
chmod +x .github/hooks/scripts/*.sh

Exécuter une session de base

Démarrez une nouvelle session Copilot CLI dans le référentiel :

Bash
copilot -p "Show me the status of this repository"

Résultats attendus :

  • Vous voyez la bannière de politique (de sessionStart).
  • Une nouvelle entrée est ajoutée à .github/hooks/logs/audit.jsonl (à partir de userPromptSubmitted).

Déclencher l'utilisation de l'outil et vérifier la journalisation

Exécutez une commande qui permet à Copilot CLI d'utiliser un outil (par exemple, bash) :

Bash
copilot -p "Show me the last 5 git commits"

Résultats attendus :

  • Une preToolUse entrée est ajoutée à .github/hooks/logs/audit.jsonl.
  • Si l’appel d’outil est autorisé, l’exécution se poursuit normalement.

Tester une commande refusée

L’exemple de script de stratégie inclut une règle de démonstration temporaire qui bloque les commandes contenant la chaîne COPILOT_HOOKS_DENY_DEMO. Cela vous permet de valider le flux de refus en toute sécurité sans exécuter de commandes destructrices.

Exécutez une invite qui déclencherait une commande refusée :

Bash
copilot -p "Run a test command: echo COPILOT_HOOKS_DENY_DEMO"

Résultats attendus :

  • Copilot CLI n’exécute pas la commande.
  • Votre hook retourne une réponse de déni avec une raison claire.
  • Une policyDeny entrée est écrite dans .github/hooks/logs/audit.jsonl.

Après avoir confirmé que le flux de refus fonctionne correctement, supprimez la règle de démonstration de votre script et remplacez-la par des modèles de refus qui reflètent les stratégies de votre organisation.

Inspecter vos journaux d’audit

Pour afficher les entrées récentes :

Bash
tail -n 50 .github/hooks/logs/audit.jsonl

Pour filtrer uniquement les décisions refusées :

Bash
jq 'select(.event=="policyDeny")' .github/hooks/logs/audit.jsonl

7. Déployer en toute sécurité au sein des équipes

Après avoir validé vos hooks dans un référentiel unique, déployez-les progressivement pour éviter de perturber les flux de travail de développement.

Choisir une stratégie de déploiement

Les approches courantes de déploiement sont les suivantes :

  •         **Déploiement axé sur la journalisation (recommandé)** : commencez par journaliser les invites et l’utilisation de l’outil sans interdire l’exécution. Passez en revue les journaux pour une période donnée, puis introduisez des règles de refus une fois que vous comprenez les modèles d’utilisation courants.
    
  •         **Déploiement d’équipe par équipe** : déployez des hooks sur une équipe ou un dépôt à la fois, rassemblez des commentaires, puis développez-les vers des équipes supplémentaires.
    
  •         **Déploiement basé sur les risques** : commencez par les référentiels qui gèrent les systèmes sensibles ou l’infrastructure de production, puis développez-les vers des référentiels à faible risque.
    

Communiquer les attentes

Avant d’appliquer des règles de refus, assurez-vous que les développeurs comprennent :

  • Ces hooks sont actifs dans le référentiel
  • Quels types de commandes peuvent être bloqués
  • Procédure à suivre si une commande est refusée

La communication claire réduit la confusion et les demandes de support.

Conserver les politiques faciles à maintenir

À mesure que l’utilisation évolue :

  • Stocker la configuration et les scripts de hook dans le contrôle de version.
  • Passez régulièrement en revue les journaux d’audit pour détecter les nouveaux modèles de risque.
  • Mettez à jour les règles de refus de manière incrémentielle plutôt que d’ajouter des correspondances étendues.
  • Documentez la raison pour laquelle chaque règle de refus existe, en particulier pour les restrictions à impact élevé.

Gérer soigneusement les exceptions

Certaines équipes (par exemple, les équipes d’infrastructure ou de plateforme) peuvent nécessiter des autorisations plus larges. Pour gérer cela en toute sécurité :

  • Conservez des configurations de raccordement distinctes pour différents référentiels.
  • Conservez les exceptions étroites et bien documentées.
  • Évitez les contournements locaux ad hoc qui sapent l’auditabilité.

Lectures complémentaires

Pour résoudre les problèmes de hooks, consultez Utilisation de hooks avec les agents de GitHub Copilot.