Claude Code Berechtigungs-Audit: allow/deny und riskante Befehle in 5 Minuten prüfen
Prüfe Claude Code allow/deny-Regeln, riskante Befehle, Umgebungsvariablen und Logs jeden Morgen in 5 Minuten.
Das Audit klärt, was Claude Code heute tun darf
Das gefährlichste Claude-Code-Setup ist nicht immer das offensichtliche “alles erlauben”. Häufiger passiert etwas Leiseres: Gestern wurde Bash(git push *) oder ein breites WebFetch erlaubt, heute öffnet jemand ein produktionsnahes Repository und erinnert sich nicht mehr daran.
Diese Anleitung ist eine Morgenroutine für fünf Minuten. allow heißt: ohne weitere Nachfrage ausführen. ask heißt: jedes Mal bestätigen lassen. deny heißt: blockieren. Für Einsteiger ist das die Arbeitsfläche, die Sie dem Agenten geben.
Am 3. Juni 2026 beschreiben die offiziellen Dokumente, dass /permissions die Werkzeugrechte und die jeweilige Einstellungsquelle zeigt. Regeln werden in der Reihenfolge deny -> ask -> allow geprüft; deny gewinnt. Prüfen Sie für Richtlinien immer die aktuellen Seiten zu Claude Code Permissions, Settings und Environment variables.
Der Ablauf passt gut nach der Checkliste für die ersten 30 Minuten und vor dem Team-Setup mit der CLAUDE.md-Vorlage. Es geht nicht um Bürokratie, sondern um Arbeit, die klein genug ist, um sauber geprüft zu werden.
Die Fünf-Minuten-Struktur
Beginnen Sie mit dem Risiko der heutigen Aufgabe, nicht mit JSON. Dokumentation, Dependencies, Formulare und Deployments brauchen unterschiedliche Grenzen.
flowchart TD
A[Start session] --> B[Check git status]
B --> C[Open /permissions]
C --> D[Review allow / ask / deny]
D --> E[Inspect env and logs policy]
E --> F[Run local audit script]
F --> G[Write handoff note]
| Stelle | Prüfen | Warnsignal |
|---|---|---|
git status --short | Gibt es schon Änderungen? | Ein Diff ist da, aber niemand kennt die Herkunft |
/permissions | Aus welcher Datei stammt jede Regel? | Breites Bash, WebFetch oder Edit in allow |
.claude/settings.json | Geteilte Teamregeln | Deployment, Billing oder Produktlinks sind automatisch erlaubt |
.claude/settings.local.json | Persönliche Ausnahmen | Eine Regel von gestern ist noch aktiv |
env | Verlauf und Subprozesse | Das Team will Logs, aber CLAUDE_CODE_SKIP_PROMPT_HISTORY=1 ist gesetzt |
Ein Detail ist wichtig: Ein nacktes Bash in deny entfernt das Bash-Werkzeug aus Claudes Kontext. Eine eingegrenzte Regel wie Bash(rm *) lässt das Werkzeug sichtbar und blockiert nur passende Aufrufe. Ein Hinweis in CLAUDE.md ist Führung, aber keine technische Grenze.
Minimales settings-Beispiel für das Repository
Geteilte Einstellungen funktionieren besser, wenn riskante Aktionen früh blockiert und Entscheidungen in ask gehalten werden. Dieses Beispiel ist ein brauchbarer Startpunkt für .claude/settings.json.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)",
"Bash(git status *)",
"Bash(git diff *)",
"Read(./src/**)",
"Read(./docs/**)"
],
"ask": [
"Bash(npm install *)",
"Bash(pnpm add *)",
"Bash(git push *)",
"Bash(npm run deploy *)",
"Edit(./.github/**)"
],
"deny": [
"Bash(curl *)",
"Bash(wget *)",
"Bash(rm -rf *)",
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"WebFetch(domain:pastebin.com)"
],
"defaultMode": "default",
"disableBypassPermissionsMode": "disable"
},
"env": {
"CLAUDE_CODE_SUBPROCESS_ENV_SCRUB": "1"
}
}
Mit “harness” ist hier das Gerüst gemeint, auf dem der Agent arbeitet: Claude Code, settings, Hooks, Sandbox-Regeln und Log-Erwartungen zusammen. Man vertraut nicht einfach stärker, sondern macht die Arbeitsfläche enger und klarer.
Bash(npm run test *) verwendet einen Platzhalter. Aktuelle Dokumentation erkennt auch ein abschließendes :* wie in Bash(ls:*), aber nur am Ende des Musters. Für Teamregeln ist Bash(git push *) lesbarer.
Kopierbare Repo-Checkliste
Das Audit sollte kein langes Sicherheitsdokument werden. Fügen Sie diesen Block in PR, Issue oder Übergabe ein.
claude_code_permission_audit:
date: "2026-06-03"
repository:
name: "your-repo"
branch: "feature/your-task"
dirty_before_start: "yes/no"
allowed_today:
- "Read project files"
- "Edit MDX and test files"
- "Run npm run lint"
- "Run npm run test -- --runInBand"
ask_before:
- "Install or update packages"
- "Change auth, billing, analytics, or deploy config"
- "Push commits or create releases"
never_allow:
- "Print .env, tokens, cookies, or private keys"
- "Run curl/wget for arbitrary URLs"
- "Delete git history or force-push"
proof_required:
- "git diff reviewed"
- "test or build command captured"
- "rollback note written"
owner_handoff:
reviewer: "name"
open_questions:
- "Which production URL should be checked?"
Die wichtigste Zeile ist allowed_today. Sie beschreibt keine dauerhafte Freigabe, sondern nur den kleinsten Satz an Rechten für die heutige Aufgabe.
Riskante Permission-Pattern mit Node finden
Beim Lesen per Auge übersieht man leicht Bash als Gesamtfreigabe oder ein übrig gebliebenes Bash(npx *). Speichern Sie das Skript als scripts/audit-claude-permissions.mjs und führen Sie es im Repository aus.
#!/usr/bin/env node
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const repo = process.cwd();
const settingsFiles = [
path.join(os.homedir(), ".claude", "settings.json"),
path.join(repo, ".claude", "settings.json"),
path.join(repo, ".claude", "settings.local.json"),
].filter((file) => fs.existsSync(file));
const riskyAllowRules = [
{ pattern: /^Bash$/i, severity: "high", reason: "all Bash commands are auto-allowed" },
{ pattern: /^PowerShell$/i, severity: "high", reason: "all PowerShell commands are auto-allowed" },
{ pattern: /^(Edit|Write)$/i, severity: "high", reason: "all file edits are auto-allowed" },
{ pattern: /^WebFetch$/i, severity: "medium", reason: "all web fetches are auto-allowed" },
{
pattern: /^Bash\((curl|wget|nc|ncat|ssh|scp|rsync)\b.*\)$/i,
severity: "high",
reason: "network or transfer command is auto-allowed",
},
{
pattern: /^Bash\(.*\b(rm\s+-[^\)]*r|git\s+push|npm\s+install|pnpm\s+add|yarn\s+add|npx|docker\s+exec|devbox\s+run|mise\s+exec|terraform\s+apply|kubectl\s+apply)\b.*\)$/i,
severity: "high",
reason: "destructive or environment-changing command is auto-allowed",
},
{
pattern: /^PowerShell\(.*\b(Remove-Item|Invoke-WebRequest|Invoke-RestMethod|Start-Process)\b.*\)$/i,
severity: "high",
reason: "risky PowerShell command is auto-allowed",
},
];
const expectedDenyRules = [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl *)",
"Bash(wget *)",
];
const findings = [];
function add(file, severity, rule, reason) {
findings.push({ file: path.relative(repo, file) || file, severity, rule, reason });
}
function readJson(file) {
try {
return JSON.parse(fs.readFileSync(file, "utf8"));
} catch (error) {
add(file, "high", "JSON", `cannot parse settings: ${error.message}`);
return null;
}
}
for (const file of settingsFiles) {
const settings = readJson(file);
if (!settings) continue;
const permissions = settings.permissions ?? {};
const allow = Array.isArray(permissions.allow) ? permissions.allow : [];
const ask = Array.isArray(permissions.ask) ? permissions.ask : [];
const deny = Array.isArray(permissions.deny) ? permissions.deny : [];
if (permissions.defaultMode === "bypassPermissions") {
add(file, "high", "permissions.defaultMode", "session starts in bypassPermissions");
}
if (permissions.disableBypassPermissionsMode !== "disable") {
add(file, "medium", "permissions.disableBypassPermissionsMode", "bypass mode is not disabled here");
}
if (settings.env?.CLAUDE_CODE_SKIP_PROMPT_HISTORY === "1") {
add(file, "low", "CLAUDE_CODE_SKIP_PROMPT_HISTORY", "prompt history and transcripts are not written");
}
if (settings.env?.CLAUDE_CODE_SUBPROCESS_ENV_SCRUB !== "1") {
add(file, "low", "CLAUDE_CODE_SUBPROCESS_ENV_SCRUB", "subprocess credential scrubbing is not enabled here");
}
for (const rule of allow) {
for (const risky of riskyAllowRules) {
if (risky.pattern.test(rule)) add(file, risky.severity, rule, risky.reason);
}
}
for (const required of expectedDenyRules) {
if (!deny.includes(required)) add(file, "low", required, "consider adding this deny rule");
}
if (ask.length === 0) {
add(file, "low", "permissions.ask", "no ask rules are defined");
}
for (const rule of [...allow, ...ask, ...deny]) {
if (/:\*[^)]/.test(rule)) {
add(file, "medium", rule, "the :* shorthand only behaves as a wildcard at the end of a pattern");
}
}
}
if (settingsFiles.length === 0) {
console.log("No Claude Code settings files found in user or repo scope.");
} else if (findings.length === 0) {
console.log("No risky Claude Code permission patterns found.");
} else {
console.table(findings);
}
if (findings.some((finding) => finding.severity === "high")) {
process.exitCode = 1;
}
PowerShell-Aufruf:
New-Item -ItemType Directory -Force -Path .\scripts | Out-Null
node .\scripts\audit-claude-permissions.mjs
Das Skript ist kein vollständiger Sicherheitsmotor. Es schafft einen Prüfeinstieg. Auch wenn Bash(curl *) blockiert ist, kann ein erlaubter Bash-Befehl theoretisch ein Node-Skript starten, das selbst Netzwerkzugriff nutzt. Für stärkere Grenzen braucht man Sandbox oder Container.
Vier konkrete Anwendungsfälle
1. Artikel und Dokumentation
MDX, README, Übersetzungen und Screenshots sind meist risikoärmer. Read(./src/**), Edit(./site/src/content/**), Bash(npm run lint) und Bash(npm run test *) lassen sich oft erlauben. npm install und git push bleiben in ask.
Der Stolperstein ist der CTA. Gumroad-Links, Kontaktformulare und kostenlose PDF-Links beeinflussen Umsatz und Leads. Deshalb gehört ein öffentlicher URL-Check zur Definition of Done.
2. Dependency-Updates
Dependency-Arbeit verändert package.json, Lockfiles, Build-Verhalten und manchmal Sicherheitslage. Lassen Sie Installationen bestätigen und verlangen Sie Grund, Testkommando und Rollback-Notiz.
Ein guter Prompt lautet: “Begrenze das auf drei Update-Kandidaten und zeige Breaking-Change-Risiko, Prüfkommando und Rollback in einer Tabelle.”
3. Auth, Billing und Analytics
Login, Stripe, Gumroad, Werbe-Tags, Mailziele und Webhooks gehören hinter menschliche Freigabe. Tests reichen hier nicht. Prüfen Sie, welche Daten gesendet werden, ob Fehler doppelt abrechnen können und ob Logs personenbezogene Daten enthalten.
CLAUDE_CODE_SKIP_PROMPT_HISTORY=1 verhindert, dass Prompt-Verlauf und Sitzungs-Transkripte auf Platte geschrieben werden. Das hilft bei kurzlebigen sensiblen Sessions, schwächt aber Team-Audits.
4. Team-Übergabe
Bei der Übergabe zählt die Entscheidungsspur. Eine gute Notiz sagt, was erlaubt war, was blockiert blieb, welche Beweise vorliegen und was noch offen ist.
Handoff note:
- Allowed today: Edit content files, run lint, run unit tests.
- Asked before: package changes, deploy, payment links, analytics tags.
- Denied: .env reads, arbitrary curl/wget, recursive delete.
- Evidence: npm run lint passed, git diff reviewed.
- Remaining risk: production URL has not been checked after deploy.
Typische Fallen
Erstens: Zu breite automatische Freigaben. Bash, PowerShell, Edit oder WebFetch in allow sind bequem, lassen aber zu viel an Erinnerung und Review-Disziplin hängen.
Zweitens: URL-Filter nur über Bash-Muster. Bash(curl https://github.com *) ist fragil, weil Optionen, Redirects, Variablen und Leerzeichen variieren. Blockieren Sie curl und wget, und verwenden Sie WebFetch(domain:example.com) oder einen Hook.
Drittens: Wrapper-Befehle. Die Dokumentation beschreibt eingebaute Behandlung für Wrapper wie timeout und time. Entwicklungsrunner wie npx, docker exec, devbox run und mise exec sind anders zu bewerten.
Viertens: Read/Edit-Deny ist keine vollständige OS-Isolation. Es wirkt für eingebaute Claude-Code-Werkzeuge und erkannte Dateibefehle, aber beliebige Skripte können intern Dateien öffnen. Für starke Isolation verwenden Sie Sandbox oder Container.
Team-Prompt für den ersten Turn
Starten Sie mit Audit, nicht mit Implementierung.
Before changing files, audit Claude Code permissions for this repository.
Return:
1. allow rules that are safe for today's task
2. ask rules that should stay behind human approval
3. deny rules that protect secrets, deploys, and destructive commands
4. environment variables that affect logs or subprocess secrets
5. the smallest task you can complete with proof and rollback notes
Do not edit files until the audit is summarized.
Der Prompt erzwingt Sicherheit nicht allein. Das tun settings und Permissions-UI. Sein Nutzen liegt darin, die Grenze vor der ersten Änderung sichtbar zu machen.
Umsatzpfad schützen
Für eine Website mit kostenlosem PDF, Gumroad-Produkten oder Beratung schützt das Audit nicht nur Sicherheit, sondern Umsatz. Wer den Grundablauf noch übt, startet mit der kostenlosen Cheatsheet. Wer CLAUDE.md, Rechte, Hooks und MCP für ein Team ordnen will, kommt mit dem Setup Guide schneller ans Ziel. Für Einführung und Betrieb im echten Repository ist die Seite Training und Beratung der passende Einstieg.
Nach dem praktischen Test war die wertvollste Routine: git status, /permissions, .claude/settings.local.json und das Audit-Skript prüfen, bevor Claude Code Dateien ändert. Gumroad-Links und Deploy-Einstellungen in ask zu lassen verlangsamt die Session leicht, macht Reviews aber schneller, weil jede umsatzrelevante Änderung einen sichtbaren Freigabegrund hat.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Repo-Audit-Checkliste vor der ersten Änderung
Ein 20-Minuten-Audit für Scope, Risikobereiche, Prüfbefehle und Umsatz-CTA vor der ersten Änderung.
Claude Code Harness Lite: ein kleiner Sicherheitsrahmen für erste Änderungen
Ein einfacher Ablauf, der Lesen, Ändern, Beweise, öffentliche URLs und Umsatz-CTAs trennt.
Claude Code Repo Map im ersten Durchlauf: vorhandenen Code sicher lesen
Sicherer erster Durchlauf für bestehende Repositories mit Claude Code: Repo-Map, kleine Aufgaben, Beweise, Gratis-PDF, Gumroad und Beratung.