Blog • Claude Code / Berechtigungen
Nach Upgrade auf Claude Code 2.1.314 mit permissions.blockWritesOutsideWorkingDirectories: wie verweigerte Write- und Edit-Pfade in JSON-Logs festhalten?
Am 30. Oktober 2026 lieferte Anthropic Claude Code 2.1.314 mit permissions.blockWritesOutsideWorkingDirectories. Bei true lehnen Write, Edit und NotebookEdit Pfade außerhalb workingDirectories in jedem permission mode ab, auch default, acceptEdits und bypassPermissions.
Das ist nicht dieselbe Schicht wie allow- oder deny-Regeln in der permission policy: die steuern Tool-Typen und Freigaben, Schreiben außerhalb blockiert hart per Pfadpräfix vor der Ausführung. Audit-JSON braucht Settings-Flag, Session workingDirectories, tool und path sowie decision denied und reason outside_working_directories für write_path_gate.
Allow- und deny-Queue in Agent permission policy; Managed Agents auto-Evaluationskontext in Managed Agents auto-Evaluation; Session-Workflow-JSON in Claude Code workflow. Dieser Artikel behandelt nur 2.1.314-Blocks außerhalb der Working Directories, Log-Feldformen und write_path_gate-Verzweigung.
- Ist permissions.blockWritesOutsideWorkingDirectories in settings true, braucht die Session nicht-leere workingDirectories, sonst no_workdirs von write_path_gate.
- Write-, Edit- und NotebookEdit-JSON brauchen einen String path; fehlt er oder ist kein String → missing_path, nicht outside_working_directories.
- Liegt path unter einem workingDirectory oder darunter → allow; außerhalb wie /etc/hosts → abgelehnt mit decision denied und reason outside_working_directories im Log.
- Nicht-Schreib-Tools wie Bash und Read sind nicht im Block-Set; write_path_gate liefert not_write_tool, getrennt von deny_outside zählen.
Zuerst dies: 2.1.314 ergänzt harte Schreib-Blocks an Working-Directory-Grenzen und passende Log-Felder; allow- oder deny-Tabellen der permission policy werden nicht neu geschrieben. Unten: Changelog, settings JSON, Session workingDirectories, Write Edit NotebookEdit-Beispiele, Ablehnungs-Logs und Tabelle, write_path_gate-Quelltext, Formprüfung in JSONNote.
Wie blockiert 2.1.314 Write, Edit und NotebookEdit außerhalb der Working Directories
Änderungen stehen in Claude Code changelog, Tag-Seite Release v2.1.314. Gegenüber früheren Versionen fällt permissions.blockWritesOutsideWorkingDirectories auf: aktiviert erreichen Schreib-Tools /etc-Pfade nicht mehr via bypassPermissions oder acceptEdits.
Der Block erfolgt nach Pfadauflösung vor dem Schreiben. Logs brauchen tool-Name und absoluten path für SIEM-Aggregation auf reason outside_working_directories statt generischem permission denied.
Wie schreibt man permissions.blockWritesOutsideWorkingDirectories in settings JSON
blockWritesOutsideWorkingDirectories unter permissions in User- oder Managed-Settings auf true setzen. Der Schalter ist orthogonal zum permission mode: auch in bypassPermissions prüfen Schreib-Tools workingDirectories-Präfixe.
{
"permissions": {
"blockWritesOutsideWorkingDirectories": true
}
}
Steht der Schalter als String true oder fehlt permissions, soll Schema-Validierung zuerst schema liefern, bevor write_path_gate verzweigt. Formfehler nicht als not_enabled werten.
Wie workingDirectories und blockOutside in der Session zusammenhängen
Der Client schreibt workingDirectories-Array und blockOutside-Boolean ins Session-Context-JSON. Präfixvergleich nur bei blockOutside true und Settings an; bei blockOutside false liefert write_path_gate not_enabled, auch wenn settings true sind.
{
"workingDirectories": ["/home/dev/myapp"],
"blockOutside": true
}
workingDirectories braucht mindestens einen nicht-leeren String; leeres Array → no_workdirs. Vor dem Vergleich trailing slashes an Wurzeln entfernen; path gleich Wurzel oder beginnt mit Wurzel plus Slash.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": ["workingDirectories", "blockOutside"],
"properties": {
"workingDirectories": {
"type": "array",
"minItems": 1,
"items": { "type": "string", "minLength": 1 }
},
"blockOutside": { "type": "boolean" }
}
}
Welche Felder braucht Write-, Edit- und NotebookEdit-JSON
Audit-Beispiele brauchen mindestens tool und path. Write, Edit oder NotebookEdit starten die Schreib-Logik; path soll absolut sein. Löst der Client relative Pfade auf, speichert das Log den aufgelösten absoluten Wert für SIEM.
{
"tool": "Write",
"path": "/home/dev/myapp/src/main.ts"
}
{
"tool": "Edit",
"path": "/etc/hosts"
}
Wie decision und reason in Ablehnungsdatensätzen stehen
Liegt path unter keinem workingDirectory-Präfix, darf der Client nicht schreiben und loggt decision denied mit reason outside_working_directories plus originales tool und path. NotebookEdit teilt dieselbe reason-Enum wie Edit für eine Report-Regel über drei Schreib-Tools.
{
"tool": "Edit",
"path": "/etc/hosts",
"decision": "denied",
"reason": "outside_working_directories"
}
| Log- oder Aufrufsignal | write_path_gate liefert | Operator-Aktion |
|---|---|---|
| path unter workingDirectories-Präfix, tool Write oder NotebookEdit | allow | Ausführung erlauben; kein outside_working_directories im Log. |
| path außerhalb Wurzeln, tool Edit, blockOutside true | deny_outside | An Client-Log decision denied und reason outside_working_directories anpassen. |
| blockOutside false oder Settings-Schalter inaktiv | not_enabled | Kein outside_working_directories fälschlich; zuerst settings und Session blockOutside prüfen. |
| tool Bash, path beliebig | not_write_tool | Getrennt von Working-Directory-Schreib-Blocks zählen; Bash folgt weiter anderen permission rules. |
Wie write_path_gate zwischen schema und sieben Fachzweigen wählt
Reihenfolge: Session-Context-JSON-Schema für workingDirectories und blockOutside; blockOutside false → not_enabled; path lesen, kein String → missing_path; tool außerhalb Write, Edit, NotebookEdit → not_write_tool; leere workingDirectories → no_workdirs; path passt Präfix → allow; sonst deny_outside mit Log reason outside_working_directories.
deny_outside und missing_path nicht zu einem blocked-Bit zusammenlegen. Getrennt zählen, um falsche Pfade, falsche Tool-Typen und echte outside_working_directories-Ablehnungen zu trennen.
def actual_type(data: object) -> str:
if data is None:
return "null"
if isinstance(data, bool):
return "boolean"
if isinstance(data, list):
return "array"
if isinstance(data, int):
return "integer"
if isinstance(data, float):
return "number"
if isinstance(data, str):
return "string"
if isinstance(data, dict):
return "object"
raise TypeError(type(data))
def validate(data: object, schema: dict) -> list[str]:
errors: list[str] = []
if not isinstance(schema, dict):
return errors
types = schema.get("type")
if isinstance(types, str):
types = [types]
actual = actual_type(data)
if types and not any(t == actual or (t == "number" and actual == "integer") for t in types):
errors.append("type")
if "enum" in schema and not any(value == data for value in schema["enum"]):
errors.append("enum")
if isinstance(data, str) and "minLength" in schema and len(data) < schema["minLength"]:
errors.append("minLength")
if isinstance(data, dict) and schema.get("properties"):
for key in schema.get("required") or []:
if key not in data:
errors.append(f"required:{key}")
if schema.get("additionalProperties") is False:
for key in data:
if key not in schema["properties"]:
errors.append(f"additional:{key}")
for key, sub in schema["properties"].items():
if key in data and data[key] is not None:
errors.extend(validate(data[key], sub))
return errors
def write_path_gate(ctx: dict, call: dict, schema: dict) -> str:
if validate(ctx, schema):
return "schema"
if not ctx.get("blockOutside"):
return "not_enabled"
path = call.get("path")
if not isinstance(path, str):
return "missing_path"
tool = call.get("tool")
if tool not in {"Write", "Edit", "NotebookEdit"}:
return "not_write_tool"
roots = ctx.get("workingDirectories") or []
if not roots:
return "no_workdirs"
for root in roots:
base = root.rstrip("/")
if path == base or path.startswith(base + "/"):
return "allow"
return "deny_outside"
Wie validiert man settings, context und Ablehnungs-Logs in JSONNote
- 1Context-Form per Schema fixieren
Öffnen Sie JSON Schema. Session-Context-Schema ins erste Feld, workingDirectories- und blockOutside-Beispiel ins zweite. required- oder minItems-Fehler zuerst; bei schlechter Form kein allow oder deny_outside.
- 2Format für tool-Aufrufe
Öffnen Sie JSON formatieren, Write-, Edit- oder NotebookEdit-JSON einfügen. Prüfen, dass tool und path existieren und path ein String ist, bevor missing_path bei write_path_gate bewertet wird.
- 3Diff: erlaubte vs abgelehnte Logs
Öffnen Sie JSON Diff. Links erlaubtes Beispiel unter workingDirectory, rechts Ablehnung mit decision denied und reason outside_working_directories. Hervorgehobenes reason ist die SIEM-Schlüsselzeile.
Häufige Fragen
Kann bypassPermissions außerhalb der Working Directories schreiben?
Nein. Ab 2.1.314 mit blockWritesOutsideWorkingDirectories true blockieren Write, Edit und NotebookEdit außerhalb der Working Directories auch in bypassPermissions; Logs nutzen weiter reason outside_working_directories, bypass überspringt keine Verzeichnisprüfung.
Können Symlinks workingDirectories-Präfixprüfungen umgehen?
Der Client vergleicht Präfixe am path-String der Anfrage ohne Symlink-Ziele aufzulösen. workingDirectories auf echte Projekt-Wurzeln setzen und den vom Agent gelieferten path loggen; dieser Artikel erklärt nur Validierungslogik, keine Bypass- oder Angriffsschritte.
Steht das im Konflikt mit allow- oder deny-Regeln in der permission policy?
Kein Konflikt, andere Schicht. permission policy entscheidet Tool-Typ-Freigabe oder Queue; blockWritesOutsideWorkingDirectories blockiert außerhalb trotzdem per path. JSON getrennt halten; write_path_gate spiegelt nur Verzeichnisschicht, kein allow oder deny für policy.
Loggen Read oder Grep außerhalb workingDirectories als outside_working_directories?
Nein. outside_working_directories gilt nur für Schreib-Ablehnungen bei Write, Edit, NotebookEdit. Read-Tools folgen anderen permission- und Sandbox-Regeln; write_path_gate liefert not_write_tool, Lesezugriffe nicht in Schreib-Ablehnungsmetriken mischen.
Wie trennen Logs no_workdirs und deny_outside?
no_workdirs ist ein lokaler Gate-Zweig bei fehlenden oder leeren workingDirectories und darf reason outside_working_directories nicht fälschen. deny_outside passt zu einem konkreten vom Client abgelehnten path. schema, no_workdirs und deny_outside getrennt berichten.
Fazit
Claude Code 2.1.314 nutzt permissions.blockWritesOutsideWorkingDirectories, um Write, Edit und NotebookEdit in Working-Directory-Präfixen zu halten und bei Ablehnung decision denied mit reason outside_working_directories zu loggen. write_path_gate mit settings, Session-Context, tool-Aufrufen und Logs füttern, nicht nur permission mode-Namen beobachten.
Entscheidung: context scheitert schema → schema; blockOutside false → not_enabled; path kein String → missing_path; tool nicht Write, Edit oder NotebookEdit → not_write_tool; leere workingDirectories → no_workdirs; path unter Präfix → allow; sonst deny_outside mit Log decision denied und reason outside_working_directories.
Als Nächstes: context und settings per Schema, Format für tool und path, Diff für erlaubte vs abgelehnte Logs, write_path_gate-Rückgaben getrennt berichten.