Examen blanc CCA-F corrigé.Essayer gratuitement →

Prépa CCA-F

Hook

Hook PreToolUse qui bloque les commandes shell dangereuses

Hook Claude Code prêt à l'emploi : un script PreToolUse refuse rm -rf, git push --force ou git reset --hard avant leur exécution.

Faits vérifiés le source officiellejournal des changements

Où le placer.claude/settings.json + .claude/hooks/bloquer-commandes.sh

// settings.jsonTélécharger
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/bloquer-commandes.sh"
          }
        ]
      }
    ]
  }
}
// bloquer-commandes.shTélécharger
#!/bin/bash
# bloquer-commandes.sh — hook PreToolUse pour l'outil Bash de Claude Code.
#
# Claude Code envoie sur l'entrée standard un objet JSON décrivant l'appel
# d'outil ; la commande shell se trouve dans .tool_input.command.
# Code de sortie 2 = l'appel est bloqué et le message écrit sur stderr
# est transmis à Claude. Code de sortie 0 = le circuit normal des
# permissions s'applique.
#
# Prérequis : jq. Rendre le script exécutable :
#   chmod +x .claude/hooks/bloquer-commandes.sh
#
# Ce filtre est un garde-fou, pas une barrière infaillible : une commande
# peut être formulée autrement. Combinez-le avec des règles "deny" dans
# settings.json.
 
INPUT=$(cat)
COMMANDE=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
 
# Motifs refusés (expressions régulières étendues). Complétez la liste.
MOTIFS_INTERDITS=(
  'rm[[:space:]]+-[a-zA-Z]*r[a-zA-Z]*f'   # rm -rf, rm -fr, rm -Rf…
  'rm[[:space:]]+-[a-zA-Z]*f[a-zA-Z]*r'
  'git[[:space:]]+push.*(--force|-f([[:space:]]|$))'
  'git[[:space:]]+reset[[:space:]]+--hard'
  'git[[:space:]]+clean[[:space:]]+-[a-zA-Z]*f'
  'chmod[[:space:]]+-R[[:space:]]+777'
  'mkfs\.'
  'dd[[:space:]]+if='
  'curl[^|]*\|[[:space:]]*(ba|z)?sh'      # curl … | sh
)
 
for motif in "${MOTIFS_INTERDITS[@]}"; do
  if echo "$COMMANDE" | grep -Eq -- "$motif"; then
    echo "Commande bloquée par le hook de sécurité du projet (motif : $motif). Proposez une alternative non destructive ou demandez à l'utilisateur de l'exécuter lui-même." >&2
    exit 2
  fi
done
 
exit 0

Une consigne écrite dans CLAUDE.md reste une consigne : Claude la suit la plupart du temps, sans garantie. Un hook, lui, est une commande que Claude Code exécute systématiquement à un moment précis. Ce modèle utilise l'événement PreToolUse, déclenché avant chaque appel d'outil, pour inspecter les commandes shell et refuser celles qui détruisent des données ou réécrivent l'historique Git.

Comment ça fonctionne

Le fichier est livré en deux parties :

  • l'extrait de settings.json déclare le hook sur l'événement PreToolUse avec le filtre "matcher": "Bash", afin qu'il ne s'exécute que pour l'outil shell ;
  • le script bloquer-commandes.sh reçoit sur son entrée standard un objet JSON décrivant l'appel. Il en extrait la commande (.tool_input.command) avec jq, la compare à une liste de motifs et, en cas de correspondance, écrit une explication sur la sortie d'erreur puis quitte avec le code 2.

Le code de sortie 2 bloque l'appel d'outil, et le message d'erreur est transmis à Claude, qui peut proposer une alternative. Le code 0 laisse le circuit normal des permissions s'appliquer. Attention : un code 1 n'est pas bloquant pour Claude Code, il est traité comme une erreur non bloquante et la commande s'exécute quand même.

Installation

  1. Copiez le script dans .claude/hooks/bloquer-commandes.sh et rendez-le exécutable (chmod +x).
  2. Fusionnez l'extrait dans .claude/settings.json : si le fichier contient déjà une clé hooks, ajoutez l'entrée PreToolUse au lieu de remplacer l'objet.
  3. Vérifiez que jq est installé.
  4. Lancez /hooks dans Claude Code pour vérifier que le hook est bien pris en compte, puis demandez à Claude de supprimer un dossier de test pour observer le refus.

La commande utilise "$CLAUDE_PROJECT_DIR", variable qui pointe vers la racine du projet : le script est trouvé même si Claude a changé de répertoire.

Comment l'adapter

  • Complétez la liste MOTIFS_INTERDITS avec les commandes sensibles de votre contexte (déploiement, suppression de base de données…).
  • Pour un blocage plus riche, la documentation décrit aussi une sortie JSON avec permissionDecision à "deny", "ask" ou "allow".

Pièges fréquents

  • Se croire protégé à 100 % : une expression régulière se contourne (variables, scripts intermédiaires). Doublez ce hook par des règles deny dans settings.json.
  • Oublier le droit d'exécution : sans chmod +x, le hook échoue sans bloquer.
  • Bloquer trop large : un motif trop générique interrompt des commandes légitimes et pousse à désactiver le hook.

La leçon Les hooks présente les autres événements disponibles et leurs usages.

Documentation officielleTous les fichiers