Zabezpieczanie Claude Code przed wyciekiem
10 kwietnia 2026
Co działa, co nie działa
Macierz skuteczności warstw zabezpieczeń
| Warstwa | Mechanizm | Skuteczność | Dlaczego |
|---|---|---|---|
| CLAUDE.md instrukcje | Miękka | ⚠️ Niska | Claude może zignorować — to tylko „sugestie" dla modelu |
| .claudeignore / .gitignore | Miękka | ❌ Zerowa | Potwierdzone (sty 2026): pliki całkowicie ignorowane przez Claude Code |
| settings.json deny rules | Twarda | ⚠️ Wysoka* | Blokada runtime, ale udokumentowane bypassy przez system reminders |
| Sandbox mode | OS-level | ✅ Wysoka | Izolacja bubblewrap — Linux/WSL2 ✅, Windows natywny ❌ |
| PreToolUse hooks | Deterministyczna | ✅ Najwyższa | Skrypt shell przed każdą operacją, exit 2 = twarda blokada |
Znane bypassy deny rules (luty 2026)
Issue #8031 — system reminders ujawniają zawartość zablokowanych plików. Issue #24846 — deny rules dla .env nie są konsekwentnie egzekwowane. Nie polegaj tylko na deny rules.
Główny wniosek: Jedyne niezawodne zabezpieczenie to połączenie sandbox + deny rules + hooks.
Layer 1 — settings.json deny rules
Twarde blokady — Claude nie może odczytać ani zapisać plików dopasowanych do wzorców
Lokalizacje pliku settings.json
| Zakres | Windows | Linux/macOS |
|---|---|---|
| Globalnie | %APPDATA%\Claude\settings.json | ~/.claude/settings.json |
| Per projekt (shared) | .claude\settings.json | .claude/settings.json |
| Per projekt (lokalny) | .claude\settings.local.json | .claude/settings.local.json |
Reguły uniwersalne (Windows i Linux)
{
"permissions": {
"deny": [
"Read(./.env)", "Read(./.env.*)",
"Read(./secrets/**)", "Read(./config/credentials.*)",
"Read(**/*.pem)", "Read(**/*.key)",
"Bash(ping *)", "Bash(nslookup *)"
]
},
"cleanupPeriodDays": 7
}💡 Dlaczego blokować ping i nslookup? CVE-2025-55284 (CVSS 7.1) pokazał eksfiltrację sekretów przez zapytania DNS — te komendy były auto-zatwierdzane przez Claude Code.
Reguły Windows
"Read(C:\\Users\\tomek\\.ssh\\**)", "Read(C:\\Users\\tomek\\.aws\\**)", "Read(C:\\Users\\tomek\\.kube\\**)", "Read(C:\\Users\\tomek\\Documents\\Private\\**)", "Bash(curl *)", "Bash(Invoke-WebRequest *)", "Bash(Invoke-RestMethod *)", "Bash(iwr *)", "Bash(nc *)"
W JSON ukośniki wsteczne muszą być podwojone (\\)
Reguły Linux/macOS
"Read(~/.ssh/**)", "Read(~/.aws/**)", "Read(~/.kube/**)", "Read(/home/user/Private/**)", "Bash(curl *)", "Bash(wget *)", "Bash(nc *)"
Czym jest Bash(...) na Windows?
Na Windows narzędzie w Claude Code nadal nazywa się Bash — mimo że pod spodem uruchamia PowerShell. Reguły Bash(...) działają na obu systemach, ale musisz blokować komendy specyficzne dla swojej platformy:
| Linux | Windows (PowerShell) |
|---|---|
| curl, wget | curl (alias PS), Invoke-WebRequest, iwr, Invoke-RestMethod |
| nc | nc (jeśli zainstalowany) |
| ping, nslookup | ping, nslookup (te same) |
Jak działają deny rules
- • Blokada aplikowana przed wywołaniem narzędzia — Claude nie widzi zawartości
- • Hierarchia:
denyzawsze wygrywa nadallowiask - • Ograniczenie: system reminders mogą ominąć deny rules — dlatego potrzebny jest też sandbox (Layer 1b) i hooks (Layer 2)
Blokowanie dostępu do katalogów
Pattern Read(/ścieżka/**) blokuje katalog rekurencyjnie — działa dla Read, Glob, Grep
Deny rules blokują narzędzia Claude Code, nie blokują sieci — dlatego zawsze dodaj też blokadę curl/wget.
Windows — settings.json
Globalny: %APPDATA%\Claude\settings.json
Enterprise: C:\ProgramData\ClaudeCode\managed-settings.json
{
"permissions": {
"deny": [
"Read(C:\\Users\\tomek\\.ssh\\**)",
"Read(C:\\Users\\tomek\\.aws\\**)",
"Read(C:\\Users\\tomek\\Documents\\Private\\**)",
"Read(.\\secrets\\**)",
"Bash(curl *)",
"Bash(Invoke-WebRequest *)",
"Bash(Invoke-RestMethod *)",
"Bash(ping *)",
"Bash(nslookup *)"
]
}
}Claude Code na Windows używa PowerShell — zamiast wget blokuj Invoke-WebRequest i Invoke-RestMethod.
Linux — settings.json
Globalny: ~/.claude/settings.json
{
"permissions": {
"deny": [
"Read(/home/user/.ssh/**)",
"Read(/home/user/.aws/**)",
"Read(/home/user/Private/**)",
"Read(./secrets/**)",
"Bash(curl *)",
"Bash(wget *)",
"Bash(ping *)",
"Bash(nslookup *)"
]
}
}Hook blokujący katalogi (dla poleceń Bash których deny nie łapie)
Pobierz gotowy skrypt i umieść w .claude/hooks/:
Rejestracja hooka w settings.json — Linux:
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": ".claude/hooks/block-dirs.sh" }]
}]
}Windows:
"command": "powershell .claude\\hooks\\block-dirs.ps1"
Layer 1b — Sandbox mode
Izolacja OS-level — obejmuje też subprocesy. Zredukował liczbę monitów o 84% w testach Anthropic.
| System | Technologia | Status |
|---|---|---|
| Linux | bubblewrap | ✅ Pełne wsparcie |
| WSL2 | bubblewrap | ✅ Pełne wsparcie |
| Windows natywny | — | ❌ Nieobsługiwany (planowane, brak ETA) |
Konfiguracja sandbox (settings.json)
{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true,
"allowUnsandboxedCommands": false,
"network": {
"allowedDomains": ["github.com", "*.npmjs.org", "registry.yarnpkg.com"]
}
}
}Ograniczenia sandboxa
- • Dotyczy tylko narzędzia
Bash— Read, Write, Edit, WebFetch są poza sandboxem (rządzi nimi permissions.deny) - •
allowUnsandboxedCommands: false— bez tego Claude może samodzielnie wyłączyć sandbox gdy komenda zawiedzie - • Domain fronting może ominąć filtrowanie sieci
Na Windows (natywnym) — sandbox niedostępny
Pełny sandbox identyczny jak na Linuxie:
sudo apt-get install bubblewrap socatUruchamiaj Claude Code z terminala WSL2, nie z Windows.
Izolacja przez kontener. Gotowy projekt:
textcortex/claude-code-sandboxPolegaj wyłącznie na deny rules (Layer 1) + hooks (Layer 2). Zmniejsza ochronę.
"sandbox": { "enabled": false }Bug w Claude Code 2.1.45+ (GitHub #26374, #26494): Aplikacja próbuje montować virtiofs nawet gdy sandbox.enabled: false, powodując błąd: sandbox-helper: host share not mounted at /mnt/.virtiofs-root/shared. Workaround: wyłącz sandbox jawnie lub użyj WSL2.
Layer 2 — PreToolUse Hook
Wykrywa sekrety zanim je zapisze. Hook uruchamiany przed każdą operacją Write/Edit.
Jak działa exit code 2
- Exit
0= operacja przepuszczona normalnie - Exit
1= błąd hooka (operacja może przejść) - Exit
2= twarda blokada — operacja anulowana, Claude widzi komunikat
Krok 1: Pobierz i zainstaluj hook
Skrypt skanuje generowany kod pod kątem 13 wzorców sekretów (AWS keys, GitHub tokens, Stripe keys, hasła, connection strings i inne). Umieść go w .claude/hooks/detect-secrets.sh i nadaj uprawnienia execute.
mkdir -p .claude/hooks # skopiuj detect-secrets.sh do .claude/hooks/ chmod +x .claude/hooks/detect-secrets.sh
Krok 2: Zarejestruj hook w settings.json
{
"permissions": {
"deny": [
"Read(.env)", "Read(.env.*)",
"Read(secrets.json)",
"Read(~/.ssh/**)", "Read(~/Secrets/**)",
"Read(./secrets/**)",
"Bash(curl:*)", "Bash(wget:*)"
]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": ".claude/hooks/detect-secrets.sh" }
]
}
]
},
"cleanupPeriodDays": 7
}PostToolUse — audit log komend Bash
Windows
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{ "type": "command",
"command": "powershell -Command \"(ConvertFrom-Json $env:TOOL_INPUT).command | Out-File -Append $env:USERPROFILE\\.claude\\command-audit-log.txt\"" }]
}]Linux
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{ "type": "command",
"command": "jq -r '.tool_input.command' >> ~/.claude/command-audit-log.txt" }]
}]Alternatywa: pakiet claudeignore (npm)
Implementuje składnię .gitignore jako PreToolUse hook — daje funkcjonalność .claudeignore której Claude Code nie wspiera natywnie:
npm install -g claudeignore && claude-ignore initUwaga: to rozwiązanie zewnętrzne (npm), nie jest zarządzane przez Anthropic.
Layer 3 & 4 — CLAUDE.md i .env.example
Miękkie warstwy uzupełniające — nie zastąpią twardych blokad
Layer 3 — CLAUDE.md
Miękka warstwaLokalizacja: korzeń projektu lub globalnie — ~/.claude/CLAUDE.md
## Security — Sekrety i Hasła
### Zasady obowiązkowe:
- NIGDY nie umieszczaj haseł, tokenów,
kluczy API w kodzie źródłowym
- Używaj zmiennych środowiskowych:
process.env.SECRET_KEY
- Nie echo-uj sekretów na konsolę
- Nie czytaj pliku .env
# DOBRZE
DATABASE_URL = os.environ.get('DATABASE_URL')
# ŹLE
DATABASE_URL = "postgresql://admin:pass@..."Layer 4 — .env.example
Najlepsza praktykaPlik .env zawiera prawdziwe hasła i klucze API — dlatego nigdy nie commituj go do repozytorium. Zamiast niego trzymaj w repo .env.example z identyczną strukturą, ale zamiast prawdziwych wartości wpisz placeholdery. Dzięki temu Claude (i inni deweloperzy) wiedzą jakie zmienne są potrzebne, ale nie mają dostępu do prawdziwych sekretów.
# .env.example — commituj do repo DATABASE_URL=postgresql://user:password@localhost/mydb STRIPE_SECRET_KEY=sk_live_your_key_here AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE GITHUB_TOKEN=ghp_your_token_here JWT_SECRET=your_jwt_secret_min_32_chars # .gitignore — zawsze .env .env.local .env.production secrets.json *.pem *.key
Nawet jeśli Claude odczyta .env.example, nie wyciekną prawdziwe sekrety.
Self-audit prompt
Wklej ten prompt w Claude gdy chcesz sprawdzić projekt pod kątem bezpieczeństwa
Do a security audit of this project. Find and report: 1. Hardcoded passwords, API keys, tokens in source code 2. Secrets in comments (TODO: change password, // key: abc123) 3. Weak generated passwords (< 12 chars, dictionary words, sequential) 4. .env files accidentally committed to git (check git history) 5. Connection strings with embedded credentials (postgresql://user:pass@...) 6. Private keys, certificates in repository 7. AWS/GCP/Azure credentials in code or config files 8. Sensitive data in log statements (console.log(password), logger.info(token)) For each finding: file, line number, severity (HIGH/MEDIUM/LOW), recommendation. Do NOT print the actual secret values — only indicate their presence.
Checklist — nowy projekt
Przed rozpoczęciem pracy z Claude Code na nowym projekcie
.claude/settings.json z deny rules — dodaj ping, nslookup (CVE-2025-55284)
Sandbox mode z allowUnsandboxedCommands: false (Linux/WSL2 — na Windows natywnym: deny rules + hooks)
Hook detect-secrets.sh / .ps1 zainstalowany (chmod +x — Linux)
PostToolUse audit hook skonfigurowany
.env dodany do .gitignore
.env.example z placeholderami — nie otwieraj prawdziwego .env w sesji
Sprawdź: git log --all --full-history -- .env (czy nie było commitowane)
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 w środowisku
Nigdy nie uruchamiaj Claude Code jako root / sudo / Administrator
cleanupPeriodDays: 7 w settings.json
Przejrzyj kod przez self-audit prompt przed pierwszą sesją
Weryfikacja że blokady działają
Test deny rules
# Zapytaj Claude: "show me contents of .env file" # Oczekiwany rezultat: "I cannot read that file due to permissions"
Test hooka (Linux)
# Zapytaj Claude: "write this to app.py: password = 'test123abc'" # Oczekiwany rezultat: # operacja zablokowana przez hook