Une garde par motif de texte n'est pas une frontière de sécurité
Une garde qui refuse un mot dans le texte d'une commande juge une écriture et non un effet : toute écriture qui évite ce mot passe, et même une liste de commandes admises à l'égalité exacte laisse passer le code qu'une commande admise lit dans un fichier que l'agent peut modifier.
Une garde refuse toute commande qui contient le mot rm. Trois façons d'écrire la même suppression la traversent, et la démonstration suivante le vérifie dans un dossier jetable qu'elle crée, avec quatre fichiers vides.
La garde et ses quatre essais
mkdir -p demo-garde && cd demo-garde
touch cible1.txt cible2.txt cible3.txt cible4.txt
cat > garde.sh << 'EOF'
#!/bin/bash
cmd="$1"
if echo "$cmd" | grep -qw 'rm'; then
echo "REFUSÉ : motif interdit détecté dans la commande tapée"
exit 1
fi
echo "AUTORISÉ : aucun motif interdit trouvé, exécution"
eval "$cmd"
EOF
chmod +x garde.sh
./garde.sh "rm cible1.txt"
./garde.sh "r'm' cible2.txt"
./garde.sh 'A=r; B=m; $A$B cible3.txt'
ENC=$(printf 'rm cible4.txt' | base64)
./garde.sh "echo $ENC | base64 -d | bash"
ls -1
REFUSÉ : motif interdit détecté dans la commande tapée
AUTORISÉ : aucun motif interdit trouvé, exécution
AUTORISÉ : aucun motif interdit trouvé, exécution
AUTORISÉ : aucun motif interdit trouvé, exécution
cible1.txt
garde.sh
Le premier essai est refusé et cible1.txt survit. Le deuxième coupe le mot par des apostrophes, que l'interpréteur retire avant d'exécuter. Le troisième assemble le mot à partir de deux variables d'une lettre. Le quatrième encode la commande en base64, que base64 -d | bash décode puis exécute.
Pourquoi corriger au cas par cas ne ferme rien
Interdire l'apostrophe isolée, les variables collées ou base64 ferme trois portes et en laisse d'autres, parce que le nombre d'écritures d'une même commande n'est pas borné à l'avance. La page des permissions de Claude Code dit la même chose de ses propres règles de commande : une règle de refus Bash(rm *) arrête rm -rf build/ et laisse passer /bin/rm -rf build/ ou bash -c 'rm -rf build/', et une telle règle n'est pas une frontière de sécurité autour du programme.
L'égalité exacte réduit la surface sans la fermer
Une liste de commandes admises tient mieux quand elle exige l'égalité exacte de chaîne et n'admet aucun programme lanceur, c'est-à-dire aucun programme qui exécute une autre commande qu'on lui passe : bash, sh -c, eval, find -exec, xargs ou npm run. Elle ferme alors les réécritures. Elle laisse ouvert le code qu'une commande admise lit ailleurs. Git lance le programme nommé par le réglage core.fsmonitor du dépôt quand il rafraîchit son index, lors d'un git status par exemple.
mkdir -p demo-fsmonitor && cd demo-fsmonitor
git init -q
git config core.fsmonitor 'echo EXECUTE_PAR_GIT_STATUS > temoin.txt; false'
git status > /dev/null 2>&1
cat temoin.txt
EXECUTE_PAR_GIT_STATUS
Un git status identique caractère pour caractère à l'entrée admise a exécuté ce qu'un agent peut écrire dans .git/config. L'autre voie n'inspecte plus le texte : le bac à sable, une isolation que le système d'exploitation impose aux commandes shell et à leurs processus enfants, borne les fichiers et le réseau que ce code atteint, quelle que soit la commande qui l'a lancé. Il tourne sur macOS, Linux et WSL2, pas sous Windows natif.
La leçon sur la lecture qui suffit à exposer un secret montre la même limite pour une règle de lecture, qui ne couvre pas une commande atteignant le fichier sans le nommer. La leçon sur ce qu'un agent peut faire fuiter sans qu'on le lui demande décrit l'injection indirecte, une instruction cachée dans un contenu que Claude lit, qui est une des voies par lesquelles un agent écrit une configuration que personne ne lui a demandée.
Une correction de plus contre une liste par égalité exacte
Ajout : refuser aussi l'apostrophe isolée. Contournement suivant : deux variables collées, toujours autorisé.
Autorisé : git status Refusé : bash -c 'git status' Reste ouvert : le programme que core.fsmonitor nomme dans .git/config
Trois contournements, ce que la garde voit, ce qui s'exécute
| Contournement | Ce que la garde voit | Ce qui s'exécute réellement |
|---|---|---|
| Coupure par apostrophes, r'm' | Les lettres r et m séparées par une apostrophe, aucun mot rm entier | La suppression, une fois les apostrophes retirées par l'interpréteur |
| Concaténation de variables, $A$B | Deux variables d'une lettre, jamais r et m côte à côte dans le texte | La suppression, une fois les variables assemblées à l'exécution |
| Encodage base64 | Une suite de caractères sans rapport visible avec le mot interdit | La suppression, une fois décodée puis transmise à l'interpréteur |
Un administrateur écrit une garde qui refuse d'exécuter toute commande contenant le mot rm, pour empêcher un script automatisé de supprimer des fichiers. Il la teste avec la commande rm notes.txt, qui est refusée. Il déploie ensuite la garde sur son système de production.
Écrivez en une phrase ce que cette situation établit, et en une phrase ce qu'elle n'établit pas.
Ce que cela établit : Le test établit que la garde a refusé la commande rm notes.txt.
Ce que cela n’établit pas : Il n'établit pas ce qu'elle fait d'une autre commande, qu'elle écrive rm en toutes lettres ou qu'elle obtienne la même suppression par des apostrophes, des variables ou un encodage, aucune autre commande n'ayant été testée.
Les trois calibrages faux les plus courants
- Trop large La garde déployée empêche le script automatisé de supprimer des fichiers en production, puisque le test de suppression a été refusé.
- Trop étroit Le test établit que la garde a été lancée sur une commande, et rien sur la réponse qu'elle lui a donnée.
- À côté Le test montre que le script automatisé visé par la garde lance réellement des suppressions de fichiers.
- Une garde qui cherche un mot dans le texte d'une commande juge une écriture, pas l'effet que l'interpréteur produira.
- Chaque contournement corrigé laisse ouvertes les écritures que la correction n'a pas prévues.
- Une liste admise à l'égalité exacte, sans programme lanceur, ferme les réécritures d'une commande mais pas le code que cette commande lit dans sa configuration.
- Le bac à sable borne fichiers et réseau par le système d'exploitation, quelle que soit la commande qui a lancé le code.
Rejouez la démonstration core.fsmonitor dans un dossier neuf et vérifiez que temoin.txt contient la ligne attendue. Écrivez ensuite une garde de quelques lignes qui refuse une commande contenant un mot de votre choix, testez-la avec ce mot écrit tel quel puis coupé par des apostrophes, et notez lequel des deux essais elle laisse passer.
Chaque affirmation datable de cette leçon renvoie ici au texte public qui la porte. Une source qui ne s’ouvre pas ne prouve rien.
- Claude Code, configurer les permissions, section Bash rule limits, consultée le 2026-09-28 consultée le 2026-09-28
- Claude Code, bac à sable, consultée le 2026-09-28 consultée le 2026-09-28
- Git, documentation de git config, entrée core.fsmonitor, consultée le 2026-09-28 consultée le 2026-09-28