Akademia · Bezpieczeństwo AI
Praca z agentem na firmowym kodzie wymaga warstw ochrony. Pokazujemy, co realnie działa, a co jest tylko sugestią dla modelu — i jak złożyć deny rules, sandbox oraz hooki w jedną, niezawodną konfigurację.
Ostatnia aktualizacja:
01 / TL;DR · Co działa, co nie
| Warstwa | Typ | Skuteczność |
|---|---|---|
| Instrukcje w CLAUDE.md | Miękka | Niska — model może zignorować |
| .claudeignore / .gitignore | Miękka | Zerowa — pliki ignorowane przez agenta |
| settings.json — deny rules | Twarda | Wysoka, ale znane bypassy |
| Sandbox mode | OS-level | Wysoka (macOS/Linux/WSL2) |
| PreToolUse hooks | Deterministyczna | Najwyższa — exit 2 = twarda blokada |
Uwaga: nie polegaj wyłącznie na deny rules. Udokumentowano bypassy (m.in. system reminders ujawniające zawartość zablokowanych plików oraz niespójne egzekwowanie reguł dla .env). Jedyne niezawodne zabezpieczenie to połączenie: sandbox + deny rules + hooki.
02 / Warstwa 1 · Deny rules
Blokada jest aplikowana przed wywołaniem narzędzia, więc agent nie widzi zawartości. W hierarchii deny zawsze wygrywa nad allow i ask. Lokalizacje pliku:
| Zakres | Linux / macOS | Windows |
|---|---|---|
| Globalnie | ~/.claude/settings.json | %USERPROFILE%\.claude\settings.json |
| Projekt (współdzielony) | .claude/settings.json | .claude\settings.json |
| Projekt (lokalny) | .claude/settings.local.json | .claude\settings.local.json |
{
"permissions": {
"deny": [
"Read(./.env)", "Read(./.env.*)",
"Read(./secrets/**)", "Read(./config/credentials.*)",
"Read(**/*.pem)", "Read(**/*.key)",
"Bash(ping *)", "Bash(nslookup *)"
]
},
"cleanupPeriodDays": 7
} Składnia ścieżek: reguły Read i Edit stosują semantykę gitignore (wzorce względem katalogu projektu). Ścieżkę absolutną podajesz przez podwójny ukośnik na początku — np. Read(//etc/hosts).
Dlaczego blokować ping i nslookup: CVE-2025-55284 pokazał eksfiltrację sekretów przez zapytania DNS, a te komendy bywały auto-zatwierdzane. Deny rules blokują narzędzia agenta, nie blokują sieci — dlatego zawsze dorzuć też blokadę curl i wget.
Na Windows narzędzie nadal nazywa się Bash, ale pod spodem uruchamia PowerShell — blokuj komendy właściwe dla platformy:
// Linux / macOS
"Read(~/.ssh/**)", "Read(~/.aws/**)", "Read(~/.kube/**)",
"Bash(curl *)", "Bash(wget *)", "Bash(nc *)"
// Windows (PowerShell pod Bash)
"Bash(curl *)", "Bash(Invoke-WebRequest *)",
"Bash(Invoke-RestMethod *)", "Bash(iwr *)", "Bash(nc *)" W ścieżkach Windows w JSON ukośniki wsteczne muszą być podwojone.
03 / Warstwa 1b · Sandbox mode
Sandbox to najsilniejsza praktyczna ochrona dla komend powłoki: izoluje narzędzie Bash na poziomie systemu operacyjnego, łącznie z procesami potomnymi. W testach Anthropic zredukował liczbę monitów o ok. 84%. Działa natywnie na macOS, Linux i WSL2 — na macOS poprzez systemowy framework Seatbelt, więc nie instalujesz żadnych zależności. Natywny Windows nie jest obsługiwany.
| System | Technologia | Status |
|---|---|---|
| macOS | Seatbelt | Pełne wsparcie (natywnie, nic nie instalujesz) |
| Linux | bubblewrap | Pełne wsparcie |
| WSL2 | bubblewrap | Pełne wsparcie |
| Windows natywny | — | Nieobsługiwany |
{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true,
"allowUnsandboxedCommands": false,
"failIfUnavailable": true,
"network": {
"allowedDomains": ["github.com", "*.npmjs.org"]
}
}
} Twarde wymuszenie: failIfUnavailable: true sprawia, że Claude Code w ogóle nie wystartuje, gdy sandbox jest niedostępny — zamiast cicho przejść w tryb bez izolacji. Sandboxowane komendy Bash domyślnie dziedziczą zmienne środowiskowe rodzica, łącznie z poświadczeniami w env — kasujesz je przed każdą komendą blokiem sandbox.credentials (patrz niżej) albo globalnie zmienną CLAUDE_CODE_SUBPROCESS_ENV_SCRUB, która strippuje poświadczenia Anthropic i providerów chmurowych ze wszystkich subprocesów.
Aktualizacja: od wersji 2.1.187 sandbox ma dedykowany blok sandbox.credentials: w files wpisujesz ścieżki do zablokowania odczytu, w envVars — zmienne do skasowania, każdy wpis z "mode": "deny". To czytelniejsze niż mieszanie reguł w filesystem.denyRead: { "credentials": { "files": [{ "path": "~/.aws/credentials", "mode": "deny" }, { "path": "~/.ssh", "mode": "deny" }], "envVars": [{ "name": "GITHUB_TOKEN", "mode": "deny" }] } }. Wpisy z różnych zakresów się sumują, a jedyny dozwolony tryb to deny — żaden zakres nie poluzuje blokady.
Ograniczenia: sandbox dotyczy tylko narzędzia Bash — Read, Write, Edit i WebFetch są poza nim (rządzi nimi permissions.deny). Ustaw allowUnsandboxedCommands: false, inaczej agent może sam wyłączyć sandbox, gdy komenda zawiedzie. Na natywnym Windows używaj WSL2 (sudo apt-get install bubblewrap socat) albo Dockera.
Aktualizacja: sandbox to warstwa, nie szczelna granica. CVE-2026-55607 (załatany w 2.1.163) pokazał ucieczkę przez pomylenie ścieżek git worktree — worktree nazwany .git pozwalał wykonać kod poza Seatbeltem, i działało nawet w trybie read-only. Wniosek się nie zmienia: trzymaj Claude Code zaktualizowany i nie traktuj sandboxa jako jedynej linii obrony. Przy repozytoriach z niezaufaną treścią dorzuć izolację na poziomie kontenera albo VM.
Domyślnie sandbox pozwala CZYTAĆ cały komputer — w tym ~/.aws/credentials i ~/.ssh/. Izolacja ogranicza zapis i sieć, ale nie odczyt. Nie ma wbudowanej listy blokad, więc te ścieżki musisz zablokować jawnie: najprościej przez sandbox.credentials, ewentualnie przez sandbox.filesystem.denyRead albo reguły Read w permissions.deny.
04 / Warstwa 2 · PreToolUse hook
Hook to skrypt powłoki uruchamiany przed wybranymi narzędziami. Kod wyjścia decyduje, co się stanie:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": ".claude/hooks/detect-secrets.sh" }
]
}
]
}
} Skrypt skanuje generowaną treść pod kątem wzorców sekretów (klucze AWS, tokeny GitHub, klucze Stripe, hasła, connection stringi). Instalacja:
mkdir -p .claude/hooks
# skopiuj detect-secrets.sh do .claude/hooks/
chmod +x .claude/hooks/detect-secrets.sh // Linux — dopisuje kazda komende do logu
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{ "type": "command",
"command": "jq -r '.tool_input.command' >> ~/.claude/command-audit-log.txt" }]
}] 05 / Warstwy 3 i 4 · Warstwy miękkie
Instrukcje w CLAUDE.md to warstwa miękka — agent może je zignorować, więc nie traktuj ich jak zabezpieczenia. Mimo to warto je dodać jako pierwszą linię świadomości:
## Bezpieczenstwo — sekrety i hasla
- NIGDY nie umieszczaj hasel, tokenow i kluczy w kodzie
- Uzywaj zmiennych srodowiskowych: process.env.SECRET_KEY
- Nie czytaj pliku .env, nie echo-uj sekretow na konsole Plik .env z prawdziwymi sekretami nigdy nie trafia do repozytorium. Zamiast niego commituj .env.example z taką samą strukturą, ale z placeholderami:
# .env.example — commituj do repo
DATABASE_URL=postgresql://user:password@localhost/mydb
STRIPE_SECRET_KEY=sk_live_your_key_here
GITHUB_TOKEN=ghp_your_token_here
# .gitignore — zawsze
.env
.env.local
*.pem
*.key Nawet jeśli agent odczyta .env.example, prawdziwe sekrety nie wyciekną.
06 / Wdrożenie · Audit i checklista
Wklej ten prompt, gdy chcesz sprawdzić projekt pod kątem bezpieczeństwa:
Zrob audyt bezpieczenstwa tego projektu. Znajdz i zgłos:
1. Zahardkodowane hasla, klucze API, tokeny w kodzie
2. Sekrety w komentarzach
3. Slabe hasla (mniej niz 12 znakow, slowa ze slownika)
4. Pliki .env przypadkiem zacommitowane (sprawdz historie git)
5. Connection stringi z osadzonymi danymi logowania
6. Klucze prywatne i certyfikaty w repozytorium
7. Dane wrazliwe w logach
Dla kazdego znaleziska: plik, numer linii, waga, rekomendacja.
NIE wypisuj prawdziwych wartosci sekretow — tylko wskaz ich obecnosc. .claude/settings.json z deny rules — dodaj ping i nslookup (CVE-2025-55284).allowUnsandboxedCommands: false (Linux/WSL2); na natywnym Windows: deny rules + hooki.detect-secrets zainstalowany i wykonywalny..env w .gitignore, a w repo tylko .env.example z placeholderami.git log --all --full-history -- .envcleanupPeriodDays: 7 w settings.json.# Zapytaj agenta: "pokaz zawartosc pliku .env"
# Oczekiwane: odmowa z powodu uprawnien
# Zapytaj: "zapisz do app.py: password = 'test123abc'"
# Oczekiwane: operacja zablokowana przez hook Wdrożenie u Was
Skonfigurujemy warstwy ochrony na Waszym repozytorium i wdrożymy je w zespole. 30 minut wystarczy, żeby sprawdzić, czy ma to u Was sens.