Modul 4b
Permissions im Detail
Vertiefung zu Modul 4 · Regeln, Muster, Auto-Mode
Was dieses Deck ergänzt
Modul 4 führt allow, ask und deny ein.
Hier geht es darum, ob eine Regel wirklich fängt, was sie fangen soll.
- Die Reihenfolge ist fest und Spezifität ändert nichts. Ein breites deny kann keine Ausnahme tragen.
- Bash-Muster greifen anders, als man denkt. Ein Leerzeichen entscheidet, Wrapper werden entfernt, eine Klasse von Werkzeugen umgeht alles.
- Pfad-Anker sind vier, und der naheliegendste ist der falsche.
- Auto-Mode ist ein zweites Tor, aber ausdrücklich keine Richtliniengrenze.
- Nicht hier: wovor man sich schützt. Bedrohungen, Prompt Injection und Sandbox stehen in Modul 9b.
# Begleitprojekt, zwei Teile
examples/permissions-demo/
.claude/settings.json # zum Auslösen
secrets/ # deny greift hier
protected/ # lesen ja, ändern nein
match.py # Muster gegen Befehl
verify.sh
# match.py prüft jedes Ergebnis gegen
# eine ERWARTUNG und endet mit Exit 1,
# wenn eines abweicht.
allow, ask, deny
allow, ask, deny — und der Klassifizierer
Die Reihenfolge ist fest
deny, dann ask, dann allow. Der erste Treffer in dieser Reihenfolge entscheidet — und die Spezifität einer Regel ändert daran nichts.
- Ein breites deny kann keine Ausnahme tragen.
Bash(aws *) in deny blockiert auch Bash(aws s3 ls) aus allow.
- Dasselbe zwischen ask und allow: eine passende ask-Regel fragt, auch wenn ein engeres allow denselben Aufruf trifft.
- Regeln werden über die Scopes hinweg zusammengeführt, nicht überschrieben. Ein deny auf irgendeiner Ebene gewinnt.
- Trifft keine Regel, entscheidet der Permission-Modus.
ein Aufruf: aws s3 ls
1. denyUser-Settings: Bash(aws *) — trifft
geblockt — hier ist Schluss
2. ask
3. allowProjekt: Bash(aws s3 ls)
keine Regel: der Permission-Modus
trifft zuerstwird nie erreicht
„Permission rules are enforced by Claude Code, not by the model."
Was im Prompt oder in CLAUDE.md steht, formt nur, was versucht wird.
checked am 2026-09-26 gegen docs/en/permissions
Nackter Name gegen Muster
Dieselbe Absicht, zwei ganz verschiedene Mechanismen.
Der Unterschied entscheidet, ob Claude Code das Werkzeug überhaupt sieht.
| deny-Regel |
Wirkung |
Bash (oder Bash(*)) | entfernt das Werkzeug ganz aus dem Kontext — es existiert für Claude Code nicht |
Bash(rm *) | lässt das Werkzeug verfügbar und blockiert erst beim Versuch |
Ein entferntes Werkzeug spart Kontext und verhindert Versuche; ein blockiertes Muster erzeugt eine sichtbare Ablehnung, aus der Claude Code lernen kann.
checked am 2026-09-26 gegen docs/en/permissions
Geschützte Pfade
Ein kleiner Satz Pfade wird nie automatisch genehmigt — und permissions.allow kann daran nichts ändern.
- Geschützt sind
.git, .claude, .vscode, .idea, .mvn und einige weitere — Repository-Zustand, Werkzeug-Konfiguration und die von Claude Code selbst.
- Die Sicherheitsprüfung läuft vor den allow-Regeln. Ein
Edit(.claude/**) in den Settings ändert das Ergebnis nicht.
- Automatisch freigegeben nur in
bypassPermissions — und im Plan Mode, wenn die Session mit Bypass-Option gestartet wurde. auto fragt den Klassifizierer, dontAsk lehnt ab.
- In den fragenden Modi bietet die Rückfrage an, Änderungen an
.claude/ für diese Session freizugeben.
# diese Regel ändert nichts:
"allow": ["Edit(.claude/**)",
"Edit(.git/**)"]
# Claude Code fragt trotzdem:
Edit .claude/settings.json ... [y/n]
# Reihenfolge der Auswertung:
1. Sicherheitsprüfung # geschützte Pfade
2. deny
3. ask
4. allow # kommt zu spaet
Claude Code prüft geschützte Pfade vor jeder allow-Regel.
Diese Prüfung lässt sich nicht wegkonfigurieren.
checked am 2026-09-26 gegen docs/en/permission-modes
Matching bei Bash
Wo Muster greifen — und wo sie danebengreifen
Das Leerzeichen entscheidet
Ein Stern trifft beliebige Zeichenfolgen einschließlich Leerzeichen — ein Platzhalter kann also mehrere Argumente überspannen.
Das Leerzeichen davor erzwingt eine Wortgrenze.
Bash(ls *) trifft ls -la, aber nicht lsof.
Bash(ls*) trifft beide — ohne Leerzeichen keine Wortgrenze.
Bash(ls:*) ist gleichbedeutend mit Bash(ls *). Der Permission Prompt schreibt die Leerzeichen-Form.
- Aber nur am Ende: in
Bash(git:* push) ist der Doppelpunkt ein wörtliches Zeichen und trifft keine Git-Befehle.
$ python3 match.py
ls -la allow
lsof -i fragt nach
git merge main allow
# 'git * main' trifft 'git merge main'
# UND 'git push origin main' -- ein
# Stern ueberspannt beide Argumente.
checked am 2026-09-26 gegen docs/en/permissions
Wrapper werden entfernt
Vor dem Abgleich entfernt Claude Code einen festen, nicht konfigurierbaren Satz Wrapper.
Was nicht darin steht, ist die Lücke.
- Entfernt:
timeout, time, nice, nohup, stdbuf, command, builtin, noglob. Also trifft Bash(npm test *) auch timeout 30 npm test.
- Nacktes
xargs auch — aber xargs -n1 … nicht: mit Flags gilt es als eigener Befehl.
- Führende Variablenzuweisungen werden bei allow nur für bekannte Variablen entfernt, bei deny und ask für jede.
watch, setsid, ionice, flock sowie find -exec und find -delete gibt keine Präfixregel frei. Im Modus manual fragen sie immer; freigeben lässt sich nur der exakte Befehl.
"allow": ["Bash(npm test *)"]
npm test # trifft
timeout 30 npm test # trifft (entwrappt)
nice -n5 npm test # trifft
xargs npm test # trifft (nackt)
xargs -n1 npm test # trifft NICHT
watch npm test # fragt IMMER
# und die Lücke:
"allow": ["Bash(devbox run *)"]
devbox run rm -rf . # erlaubt
Umgebungs-Runner stehen nicht in der Liste. Bash(devbox run *) erlaubt alles, was nach run kommt — einschließlich devbox run rm -rf ..
Dasselbe gilt für direnv exec, mise exec, npx und docker exec.
checked am 2026-09-26 gegen docs/en/permissions
Zusammengesetzte Befehle
Claude Code zerlegt zusammengesetzte Befehle an den Shell-Operatoren.
allow muss jeden Teilbefehl treffen, für deny und ask genügt einer.
- allow muss jeden Teilbefehl treffen. Trenner sind
&&, ||, ;, |, |&, & und Zeilenumbrüche: Bash(safe-cmd *) erlaubt nicht safe-cmd && other-cmd.
- deny und ask greifen, sobald ein Teilbefehl passt — auch in
$(…), in einer Subshell oder im Rumpf einer for-Schleife.
- Die Parameterform
Bash(command:rm *) ignoriert Claude Code mit Startwarnung: Ein zusammengesetzter Befehl käme an ihr vorbei.
- Ein fester Nur-Lese-Satz läuft in jedem Modus ohne Rückfrage:
ls, cat, grep, find, wc, lesende Formen von git und weitere. Erweitern lässt er sich nicht.
"allow": ["Bash(safe-cmd *)"]
safe-cmd --x # erlaubt
safe-cmd && other-cmd # fragt
safe-cmd | other-cmd # fragt
# Trenner: && || ; | |& & Zeilenumbruch
# wird ignoriert, mit Startwarnung:
"deny": ["Bash(command:rm *)"]
# Regel greift nie
Wer für ein Nur-Lese-Kommando trotzdem eine Rückfrage will, schreibt eine ask- oder deny-Regel dafür.
checked am 2026-09-26 gegen docs/en/permissions
Warum Argument-Muster brüchig sind
Die Doku warnt ausdrücklich: Muster, die Argumente einschränken sollen, halten nicht.
Schon eine andere Schreibweise kommt daran vorbei.
- Option vor der Adresse:
curl -X GET http://…
- Anderes Protokoll:
https:// statt http://
- Weiterleitung:
curl -L http://kurz.example.com/xyz landet doch bei GitHub
- Variable:
URL=http://github.com && curl $URL
- Anderer Aufruf desselben Programms:
/usr/bin/curl … oder sh -c 'curl …'
"deny": ["Bash(curl http://github.com/ *)"]
# alle laufen daran vorbei:
curl -X GET http://github.com/x
curl https://github.com/x
curl -L http://kurz.example.com/x
URL=http://github.com && curl $URL
/usr/bin/curl http://github.com/x
sh -c 'curl http://github.com/x'
# und der Weg bleibt ohnehin offen:
wget http://github.com/x
python3 -c "import urllib.request"
curl zu verbieten verhindert keinen Netzzugriff. Es verbietet einen Weg.
Ist Bash erlaubt, erreicht Claude Code jede Adresse — mit wget, mit Python, mit dem nächsten Werkzeug.
checked am 2026-09-26 gegen docs/en/permissions
Pfade
Welcher Anker gilt, und wie tief die Regel greift
Einer der Anker ist eine Falle
Read- und Edit-Regeln benutzen gitignore-Syntax.
Der Anker entscheidet, wogegen ein Pfad aufgelöst wird.
//pfad
Dateisystem-Wurzel
absolut, überall gleich
~/pfad
Heimatverzeichnis
absolut, pro Benutzer
/pfad
die Settings-Dateinicht die Wurzel
die Falle: sieht absolut aus, ist es nicht
pfad · ./pfad
aktuelles Verzeichnis
wandert mit dem Aufruf
je Zeile: Muster — wogegen es aufgelöst wird — was daraus folgt
Read(/secrets/**) in den User-Settings blockiert ~/.claude/secrets/** — und nicht das Projektverzeichnis.
Wer aus den User-Settings in jedes Projekt wirken will, braucht // oder ~/.
checked am 2026-09-26 gegen docs/en/permissions
allow und deny treffen verschieden tief
Dieselbe Zeile trifft je nach Rolle verschieden tief.
Das gilt für relative Muster mit genau einem Verzeichnissegment.
- Als allow trifft
Edit(src/**) nur <cwd>/src und darunter.
- Als deny oder ask trifft dieselbe Zeile ein
src in jeder Tiefe — also auch vendor/pkg/src/.
- Für jede Tiefe auch bei allow:
Edit(**/src/**) schreiben.
- Nackte Dateinamen folgen gitignore-Semantik und treffen überall:
Read(.env) ist dasselbe wie Read(**/.env).
# dieselbe Zeile, zwei Bedeutungen
"allow": ["Edit(src/**)"]
<cwd>/src/App.java # trifft
vendor/pkg/src/x.java # trifft NICHT
"deny": ["Edit(src/**)"]
<cwd>/src/App.java # trifft
vendor/pkg/src/x.java # trifft AUCH
# fuer jede Tiefe auch bei allow:
"allow": ["Edit(**/src/**)"]
Eine Schutzregel soll auch die verschachtelte Kopie treffen, eine Freigabe nicht.
Bei Symlinks dieselbe Logik: allow verlangt, dass beide Pfade passen, deny greift, wenn einer passt.
checked am 2026-09-26 gegen docs/en/permissions
Auto-Mode
Das zweite Tor — und warum es keine Grenze ist
Der Klassifizierer
Im Auto-Mode prüft ein Klassifizierer die Aufrufe, statt euch zu fragen.
deny- und ask-Regeln wertet Claude Code vorher aus.
- Er blockt, was unumkehrbar oder zerstörend ist oder aus der eigenen Umgebung hinausführt.
- Standardmäßig traut er nur dem Arbeitsverzeichnis und den Remotes des aktuellen Repositorys. Alles andere ist geblockt, bis es in
environment steht.
- Er liest dieselbe CLAUDE.md wie das Modell. „Niemals force-pushen" dort steuert damit beide.
autoMode liest er nicht aus Projekt- und Local-Settings — welche Schlüssel ein Repo nicht setzen kann: Modul 10b.
# eingebaute Regeln ansehen
claude auto-mode defaults
# wirksame Konfiguration, mit eigenen
claude auto-mode config
# Quellen, die er liest:
ja ~/.claude/settings.json
ja CLAUDE.md # dieselbe wie das Modell
nein .claude/settings.json # Projekt
nein .claude/settings.local.json
# sonst schriebe sich ein Repo Freigaben
checked am 2026-09-26 gegen docs/en/auto-mode-config
Die Stufen im Klassifizierer
Innerhalb des Klassifizierers gilt eine eigene Rangfolge.
Die interessanteste Stufe ist die ausdrückliche Absicht.
nichts hebt es auf
hard_denyblockt unbedingt
Absicht und allow greifen nicht
allow oder Absicht
soft_denyblockt als Nächstes
kann aufgehoben werden
passende Regel
allowhebt soft-Regeln auf
als Ausnahme
eure Nachricht
ausdrückliche Absichthebt den Rest auf
nur wenn sie genau die anstehende Handlung nennt
unbedingtvom Menschen aufhebbar
„Räum das Repository auf" erlaubt kein Force-Push.
„Force-push diesen Branch" erlaubt es.
Allgemeine Aufträge zählen nicht als Absicht.
checked am 2026-09-26 gegen docs/en/auto-mode-config
Auto-Mode ist keine Grenze
Die Einträge aller Ebenen werden zusammengeführt.
Eine Entwicklerin kann Firmen-Einträge nicht entfernen — aber sie kann sie aushebeln.
- Ein selbst hinzugefügtes
allow hebt ein soft_deny der Organisation auf, weil allow-Regeln innerhalb des Klassifizierers als Ausnahmen wirken.
- Die Doku sagt es selbst: „additive, not a hard policy boundary."
- Wer eine echte Grenze braucht, nimmt
permissions.deny in den Managed Settings — das blockt, bevor der Klassifizierer befragt wird.
# Organisation setzt:
soft_deny: git push --force
# Entwicklerin setzt bei sich:
allow: git push --force
# Ergebnis: erlaubt.
# allow wirkt im Klassifizierer als
# Ausnahme -- "additive, not a hard
# policy boundary"
# echte Grenze, Managed Settings:
"deny": ["Bash(git push --force *)"]
Der Klassifizierer ist Komfort, nicht Kontrolle.
Er senkt die Approval Fatigue; eine Richtlinie ersetzt er nicht.
checked am 2026-09-26 gegen docs/en/auto-mode-config
Modul 4b in fünf Sätzen
Was von diesem Deck hängenbleiben soll.
- deny, ask, allow — und Spezifität zählt nicht. Ein breites deny kann keine Ausnahme tragen.
- Das Leerzeichen vor dem Stern entscheidet, und Wrapper werden vorher entfernt. Umgebungs-Runner nicht:
Bash(devbox run *) erlaubt alles.
curl zu verbieten verhindert keinen Netzzugriff, sondern einen Weg. Argument-Muster halten nicht.
- Ein einzelner Schrägstrich ist kein absoluter Pfad, und dieselbe Pfadregel trifft in deny tiefer als in allow.
- Auto-Mode ist Komfort, nicht Kontrolle. Die echte Grenze ist
permissions.deny in Managed Settings.
Glossar Glossar
Permission-Regel
Ein Eintrag der Form Werkzeug oder Werkzeug(Muster) in allow, ask oder deny. Durchgesetzt von Claude Code selbst, nicht vom Modell.
Permission Prompt
Die Rückfrage, die Claude Code stellt, wenn keine Regel greift. Die dort angebotene Regel landet auf Wunsch dauerhaft in den Settings — meist als Präfixmuster.
Klassifizierer (Auto-Mode)
Ein zweites Tor nach den Permission-Regeln, das unumkehrbare, zerstörende und nach außen führende Handlungen blockt. Gesteuert über Prosa-Regeln in autoMode. Komfort, keine Richtliniengrenze.
Managed Settings
Von der Organisation ausgerollte Konfiguration, die keine andere Ebene überschreiben kann — auch kein Kommandozeilenargument. Einzige Ebene, auf der bestimmte Sperrschlüssel gelten.
Workspace Trust
Die Bestätigung, dass man einem Projektverzeichnis vertraut. Erst danach wirken allow-Regeln und zusätzliche Verzeichnisse aus der Projektkonfiguration. deny und ask sind davon unberührt.
MCP (Model Context Protocol)
Offenes Protokoll, über das Claude Code fremde Systeme als Werkzeuge anbindet. Für Permissions relevant, weil MCP-Werkzeuge eigene Regelformen haben: mcp__server für alle Werkzeuge eines Servers, mcp__server__tool für eines.
Sandbox
Durchsetzung auf Betriebssystemebene für Dateisystem und Netz, die nur Bash-, PowerShell- und Monitor-Befehle und deren Child-Processes betrifft. Hält auch dann, wenn die Entscheidung des Modells unterlaufen wurde.
© 2026 CGS IT Solutions GmbH
Alle Rechte vorbehalten
Diese Schulungsunterlagen sind urheberrechtlich geschützt. Vervielfältigung,
Weitergabe oder kommerzielle Nutzung — auch in Auszügen — nur mit
ausdrücklicher schriftlicher Genehmigung der CGS IT Solutions GmbH.
cgsit-claude-training · Modul 4b · Permissions · v2.0.1