Module 7 — Permissions, modes d'exécution, sandbox et fichiers de settings
Le module 6 a montré qu'une skill pré-approuve quelques outils pour un tour. Ce module s'occupe de la couche du dessous : les règles générales qui décident, pour toute la session, ce que Claude peut lire, écrire, exécuter et joindre. C'est la couche à poser dès l'ouverture d'un dépôt : elle protège .env, laisse tourner make test sans confirmation, isole les commandes Bash avec le sandbox, et décide qui approuve les gestes de Claude — vous, un classifieur, ou personne.
Le modèle de permissions
Une règle de permission a la forme Outil ou Outil(spécificateur). Elle vit dans une liste permissions.allow, permissions.ask ou permissions.deny d'un fichier de settings, ou dans un flag CLI (--allowedTools, --disallowedTools, --permission-mode). Les règles sont évaluées deny d'abord, puis ask, puis allow ; le premier match décide. Un deny ne porte pas d'exception, un ask général force la question même si un allow plus précis correspond.
| Forme | Effet |
|---|---|
Bash ou Bash(*) | Toute commande Bash. En deny, retire l'outil du contexte. |
Bash(npm run *) | Toute commande commençant par npm run, y compris npm run seul. |
Bash(git *) | Toute commande git — couvre aussi git push. |
Edit(app/**) | Édition sous app/ (gitignore-style, ancré à la source du settings). |
Edit(/src/**) | Ancré à la racine du projet en settings de projet. Un // unique ancre à la racine du système. |
Read(./.env) | Bloque la lecture du .env courant ; bloque aussi Edit et Write sur ce chemin (v2.1.208+/v2.1.228+). |
WebFetch(domain:example.com) | Fetch vers example.com. domain:*.example.com couvre les sous-domaines. |
mcp__github__get_* | Outils MCP dont le nom commence par get_ sur le serveur github. |
Agent(Explore) | Sous-agent nommé Explore. |
Cd(~/code/**) | Cible autorisée pour /cd. Un allow bascule /cd en mode allowlist. |
Deux règles à retenir sur le Bash : le * matche n'importe quel texte y compris des espaces, et Claude Code connaît les opérateurs de shell — un Bash(safe-cmd *) en allow ne couvre pas safe-cmd && rm -rf .. Les séparateurs reconnus sont &&, ||, ;, |, |&, & et le saut de ligne. Pour > fichier, le chemin cible passe par les règles Edit et par les chemins protégés.
La commande /permissions ouvre un dialogue interactif où l'on voit chaque règle, sa portée et son fichier d'origine ; les modifications prennent effet au prochain appel d'outil dans le même tour (v2.1.234+).
Les six modes d'exécution
Le mode d'exécution décide qui approuve les appels d'outils que les règles ne tranchent pas. Six valeurs sont exposées via permissions.defaultMode ou le flag --permission-mode.
| Mode | Ce qui tourne sans demande |
|---|---|
default (labellisé Manual) | Lectures seules. Demande sur chaque édition et chaque Bash hors liste read-only intégrée. |
acceptEdits | Lectures, éditions dans les répertoires de travail, plus mkdir, touch, mv, cp, rm, rmdir, sed. |
plan | Lecture et exploration seulement, aucune édition. Le classifieur passe les commandes shell si auto est disponible. |
auto | Tout, avec un classifieur (petit modèle) qui refuse les actions dangereuses. Par défaut sur Pro/Max/Team depuis la v2.1.228 (macOS/Linux/WSL). |
dontAsk | Uniquement les allow explicites et les commandes read-only ; tout le reste refusé. Idéal pour la CI. |
bypassPermissions | Tout, sauf quelques gardes (chemins critiques). À réserver aux containers isolés. --dangerously-skip-permissions en est l'équivalent. |
Shift+Tab cycle les modes dans la CLI ; auto apparaît quand il est disponible ; bypassPermissions n'apparaît qu'après un lancement explicite. En settings managés, permissions.disableBypassPermissionsMode et permissions.disableAutoMode mis à "disable" bloquent respectivement bypass et auto. La valeur auto en defaultMode ne prend pas dans .claude/settings.json ni .local.json — il faut la placer dans ~/.claude/settings.json ou en settings managés.
Chemins protégés et critiques
Deux jeux de chemins ne sont jamais auto-approuvés sauf en bypassPermissions.
- Chemins protégés —
.git,.claude(sauf.claude/worktrees),.vscode,.idea,.husky,.devcontainer,.gitconfig,.bashrc,.zshrc,.npmrc,.mcp.json,.claude.json, etc. Une écriture demande en Manual/acceptEdits, passe au classifieur enauto, est refusée endontAsk. - Chemins critiques pour
rm/rmdir— racine/, répertoires de premier niveau (/usr,/etc…), répertoire personnel,C:\, répertoire courant et ses parents. Ni unallowni un hookPreToolUsene peuvent approuver unrm -rfsur ces chemins.
Le sandbox Bash
Le sandbox est le complément OS des règles : il applique un pare-feu filesystem et réseau à chaque commande shell et à ses enfants. Sur macOS il utilise Seatbelt (rien à installer) ; sur Linux et WSL2 il s'appuie sur bubblewrap et socat (à installer). Windows natif n'est pas supporté — passer par WSL2.
/sandbox ouvre un panneau à trois onglets (Mode, Overrides, Config), plus Dependencies si un paquet manque. Le choix va dans .claude/settings.local.json. Pour activer partout, sandbox.enabled: true dans ~/.claude/settings.json.
Deux modes de sandbox, indépendants du mode de permission :
- Auto-allow : les commandes sandboxables tournent sans demande ; les autres (hôte non allowlisté, incompatibilité) retombent dans le flux normal. Un
Bash(*)enaskest ignoré pour les commandes sandboxées (sauf en plan). - Regular permissions : le sandbox isole, mais chaque commande passe par le flux de permission.
Par défaut, une commande sandboxée écrit dans le répertoire de travail, le tmp de session et les répertoires ajoutés (--add-dir, permissions.additionalDirectories). On élargit avec sandbox.filesystem.allowWrite ; on restreint avec denyWrite, denyRead. Le réseau est allowlisté par domaine via sandbox.network.allowedDomains, dont les entrées fusionnent entre scopes au lieu de se remplacer.
Une commande qui ne peut vraiment pas être sandboxée peut être retentée avec le paramètre dangerouslyDisableSandbox (« unsandboxed retry ») ; en Manual elle demande, en auto le classifieur juge. Pour couper cette échappatoire : sandbox.allowUnsandboxedCommands: false.
Fichiers de settings et précédence
Claude Code lit ses réglages dans cinq sources, dans un ordre strict — le premier qui définit une clé gagne.
| Rang | Source | Chemin ou origine | Portée |
|---|---|---|---|
| 1 | Managed | managed-settings.json, MDM, console claude.ai | Organisation (irremplaçable, sauf exceptions) |
| 2 | CLI --settings | JSON inline ou fichier | Cette session |
| 3 | Projet local | .claude/settings.local.json | Vous, ce projet (non commité) |
| 4 | Projet partagé | .claude/settings.json | Toute l'équipe (à commiter) |
| 5 | Utilisateur | ~/.claude/settings.json | Vous, tous vos projets |
Les variables d'environnement ne sont pas un niveau : pour chaque comportement, la doc précise si la variable gagne (ANTHROPIC_MODEL gagne sur model) ou cède (ANTHROPIC_DEFAULT_MODEL ne prend que si aucun fichier ne définit model). Un deny dans n'importe quel scope bloque un allow d'un autre : la précédence deny > ask > allow s'applique à travers les scopes ; --allowedTools ne contredit pas un deny managé.
Clés principales de permissions : allow, ask, deny, additionalDirectories, blockReadsOutsideWorkingDirectories, defaultMode, disableBypassPermissionsMode, disableAutoMode. allowManagedPermissionRulesOnly réserve les règles aux settings managés. Autres clés utiles : apiKeyHelper (commande shell qui génère la clé API), awsAuthRefresh (rafraîchit Bedrock), env (variables injectées), skillOverrides (visibilité de skills), sandbox.*. La commande /config clé=valeur (v2.1.181+) écrit une clé sans ouvrir le menu.
Un .claude/settings.local.json commité perd son statut personnel et devient une source de projet ; ses règles restent en attente tant que la confiance d'espace de travail n'est pas accordée. Idem si .claude est un lien symbolique.
Variables d'environnement clés
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1— désactive les sous-agents en arrière-plan etbackground: true.CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1— nettoie l'environnement des sous-processus (utile en sandbox Linux).CLAUDE_CODE_USE_BEDROCK=1,CLAUDE_CODE_USE_VERTEX=1— activent Bedrock/Vertex et exposent/setup-bedrock,/setup-vertex.CLAUDE_CONFIG_DIR— déplace le répertoire de configuration hors de~/.claude.DISABLE_DOCTOR_COMMAND=1— cache/doctor.
Fil rouge : verrouiller Kiosque
Après trois modules sur Kiosque sans filet, on pose des permissions. Le fichier partagé (.claude/settings.json, commité) définit ce que toute l'équipe doit avoir ; le fichier local personnel affine.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"defaultMode": "acceptEdits",
"additionalDirectories": ["../kiosque-migrations"],
"allow": [
"Bash(make test)",
"Bash(make lint)",
"Bash(make dev)",
"Bash(pytest *)",
"Bash(ruff *)",
"Bash(mypy *)",
"Bash(git status *)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(gh pr *)",
"Edit(app/**)",
"Edit(tests/**)",
"Edit(web/src/**)",
"WebFetch(domain:fastapi.tiangolo.com)",
"WebFetch(domain:docs.python.org)"
],
"ask": [
"Bash(git push *)",
"Bash(alembic upgrade *)"
],
"deny": [
"Read(./.env)",
"Read(./secrets/**)",
"Edit(./migrations/**)",
"Bash(rm -rf *)",
"Bash(git push --force*)",
"Bash(git push -f *)",
"Bash(git reset --hard *)"
]
},
"sandbox": {
"enabled": true,
"network": {
"allowedDomains": ["*.pypi.org", "registry.npmjs.org", "*.github.com"]
}
}
}
Karim ouvre le projet et accepte la confiance d'espace de travail. En Manual pur la journée serait pénible ; acceptEdits laisse passer les éditions dans les répertoires de travail. Les pushes forcés sont bloqués net, un git push normal demande, les migrations SQL restent bloquées à l'édition. Léa a son fichier personnel pour le front :
{
"permissions": {
"allow": ["Bash(npm run *)", "Bash(pnpm *)", "WebFetch(domain:vitejs.dev)"]
}
}
Une semaine plus tard, un audit /permissions montre douze blocages sur Bash(alembic downgrade *). On complète le ask plutôt que de tout ouvrir, on commite. En cas de doute, claude doctor liste les règles rejetées et --debug explique un refus.
.claude/settings.local.json commité change de statutUne fois commité (ou .claude en lien symbolique), Claude Code le traite comme source de projet et retient ses règles jusqu'à la confiance d'espace de travail — protection contre le dépôt qui s'auto-autoriserait des Bash(*).
En résumé
- Les règles de permission ont la forme
Outil(spécificateur)et sont évaluées deny > ask > allow ; un deny d'un scope bloque un allow d'un autre. - Les six modes —
default(Manual),acceptEdits,plan,auto,dontAsk,bypassPermissions— décident qui approuve.Shift+Tabcycle,--permission-modefixe au lancement. - Chemins protégés (
.git,.claude,.env,.mcp.json…) et chemins critiques (rm -rf /,~, dossier courant) ne sont jamais auto-approuvés, saufbypassPermissions. - Le sandbox Bash applique un pare-feu OS sur les commandes shell et leurs enfants :
sandbox.enabled,sandbox.filesystem.allow/denyWrite,sandbox.network.allowedDomains. Deux modes : auto-allow et regular. - Précédence de settings : managed > CLI
--settings> projet local > projet partagé > utilisateur. UndefaultMode: "auto"en.claude/settings.jsonne prend pas — il doit être en utilisateur ou managed. /permissionsajuste en live,/statusmontre les sources chargées,claude doctorliste les règles rejetées.
Module suivant : Mode plan, checkpoints, sessions et worktrees : travailler sans peur — les filets de sécurité côté conversation, code et git qui rendent l'expérimentation réversible.