Erweiterung 3
Permissions im Detail
Vertiefung zu Modul 9 · Regeln, Muster, Auto-Mode
Was dieses Deck ergänzt
Modul 9 sagt, dass man den Radius eng zieht.
Hier geht es darum, ob die 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 Erweiterung 6.
# Begleitprojekt, zwei Teile
examples/permissions-demo/
.claude/settings.json # zum Ausloesen
secrets/ # deny greift hier
protected/ # lesen ja, aendern nein
match.py # Muster gegen Befehl
verify.sh
# match.py prueft 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, gilt der Berechtigungsmodus.
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 Berechtigungsmodus
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 — nicht, was erlaubt ist.
checked am 2026-07-29 gegen code.claude.com/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-07-29 gegen code.claude.com/docs/en/permissions
Geschützte Pfade
Ein kleiner Satz Pfade wird nie automatisch genehmigt — und permissions.allow kann daran nichts ändern.
- Geschützt sind unter anderem
.git, .config/git und .claude — Repository-Zustand und die eigene Konfiguration von Claude Code.
- Die Sicherheitsprüfung läuft vor den allow-Regeln. Ein
Edit(.claude/**) in den Settings ändert das Ergebnis nicht.
- Ausnahme ist nur
bypassPermissions und Planung mit verfügbarem Bypass.
- In den fragenden Modi bietet die Rückfrage an, Änderungen an
.claude/ für diese Sitzung freizugeben.
# diese Regel aendert nichts:
"allow": ["Edit(.claude/**)",
"Edit(.git/**)"]
# Claude Code fragt trotzdem:
Edit .claude/settings.json ... [y/n]
# Reihenfolge der Auswertung:
1. Sicherheitspruefung # geschuetzte Pfade
2. deny
3. ask
4. allow # kommt zu spaet
Das ist die Antwort auf „ich habe es doch erlaubt".
Manche Grenzen sind keine Regeln, sondern eingebaute Prüfungen — sie stehen vor der Regelauswertung und lassen sich nicht wegkonfigurieren.
checked am 2026-07-29 gegen code.claude.com/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-07-29 gegen code.claude.com/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, flock und find -exec fragen immer und lassen sich nicht per Präfix freigeben.
"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 Luecke:
"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-07-29 gegen code.claude.com/docs/en/permissions
Zusammengesetzte Befehle
Claude Code kennt Shell-Operatoren.
Eine Regel muss jeden Teilbefehl einzeln treffen — sonst greift sie nicht.
- Erkannte Trenner:
&&, ||, ;, |, |&, & und Zeilenumbrüche.
Bash(safe-cmd *) erlaubt nicht safe-cmd && other-cmd — und genau deshalb ist Bash(command:rm *) als Parameterregel verboten und wird mit Startwarnung ignoriert.
- Bei „nicht mehr fragen" wird pro Teilbefehl eine eigene Regel gespeichert, höchstens fünf.
- Ein fester Nur-Lese-Satz läuft in jedem Modus ohne Rückfrage:
ls, cat, grep, find, wc, lesende Formen von git und weitere. Nicht konfigurierbar.
"allow": ["Bash(safe-cmd *)"]
safe-cmd --x # erlaubt
safe-cmd && other-cmd # fragt
safe-cmd | other-cmd # fragt
# Trenner: && || ; | |& & Zeilenumbruch
# deshalb verboten und ignoriert:
"deny": ["Bash(command:rm *)"]
# -> Startwarnung, Regel greift nie
Wer für ein Nur-Lese-Werkzeug trotzdem eine Rückfrage will, braucht eine ask- oder deny-Regel.
checked am 2026-07-29 gegen code.claude.com/docs/en/permissions
Warum Argument-Muster brüchig sind
Die Doku warnt ausdrücklich: Muster, die Argumente einschränken sollen, halten nicht.
Fünf Varianten genügen, um daran vorbeizukommen.
- 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
- Doppeltes Leerzeichen. Reicht schon.
"deny": ["Bash(curl http://github.com/*)"]
# alle fuenf 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
curl http://github.com/x # 2 Leerz.
# und der Weg bleibt ohnehin offen:
wget http://github.com/x
python3 -c "import urllib.request"
Und der Satz, der die ganze Folie trägt: 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-07-29 gegen code.claude.com/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-07-29 gegen code.claude.com/docs/en/permissions
allow und deny treffen verschieden tief
Dieselbe Zeile, zwei Bedeutungen — je nachdem, in welcher Rolle sie steht.
Bei einem relativen Muster mit 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/**)"]
Das ist bequem und richtig: eine Schutzregel soll auch die verschachtelte Kopie treffen, eine Freigabe soll das nicht.
Bei Symlinks dieselbe Logik — allow verlangt, dass beide Pfade passen, deny greift, wenn einer passt.
checked am 2026-07-29 gegen code.claude.com/docs/en/permissions
Auto-Mode
Das zweite Tor — und warum es keine Grenze ist
Der Klassifizierer
Auto-Mode lässt Claude Code ohne die üblichen Rückfragen laufen, indem Aufrufe durch einen Klassifizierer gehen. deny- und ask-Regeln werden vorher ausgewertet.
- 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.
- Nicht aus Projekt- und Local-Settings — ein eingecheckter Stand könnte sich sonst selbst Freigaben schreiben.
# 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
Zwei nicht-interaktive Befehle zum Nachsehen: claude auto-mode defaults druckt die eingebauten Regeln, claude auto-mode config die wirksame Konfiguration samt eigener Einträge.
checked am 2026-07-29 gegen code.claude.com/docs/en/auto-mode-config
Die Stufen im Klassifizierer
Innerhalb des Klassifizierers gilt eine eigene Rangfolge — und die vierte Stufe ist die interessante.
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-07-29 gegen code.claude.com/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 *)"]
Das ist die Folie, die man einer Sicherheitsabteilung zeigt.
Der Klassifizierer ist Komfort, nicht Kontrolle. Er senkt Abfragemüdigkeit; er ersetzt keine Richtlinie.
checked am 2026-07-29 gegen code.claude.com/docs/en/auto-mode-config
Erweiterung 3 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 als deny tiefer als als 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-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 · Erweiterung 3 · Permissions · v0.11.5