Bezpieczeństwo agentów AI: klucze API, sandbox i limity
Bezpieczeństwo agentów AI w praktyce: jak chronić klucze API, ustawić uprawnienia i sandbox w Claude Code, limity wydatków i skanowanie sekretów. Krok po kroku.
Ten artykuł w innych językach:العربيةDeutschEnglishEspañolFrançaisItaliano日本語简体中文
W tym artykule
Bezpieczeństwo agentów AI sprowadza się do trzech rzeczy: agent widzi tylko to, czego potrzebuje, klucze API nie leżą tam, gdzie agent (albo atakujący) może je przeczytać, a każdy klucz ma limit wydatków. Poniżej pięć kroków, które możemy zrobić w jedno popołudnie: uprawnienia, sandbox, porządek z kluczami, limity i skanowanie repozytoriów.
Dlaczego bezpieczeństwo agentów AI stało się pilne?
Ostatnie tygodnie dały aż nadto przykładów. Po wycieku z OpenCode użytkownicy pokazywali rachunki za cudze użycie ich kluczy, w ataku hakerskim AI na ponad 100 firm agenci włamywali się niemal bez udziału człowieka, a na wystawionych panelach Cairn leżały setki sekretów. Do tego wyciek z Meta Muse pokazał, że nawet funkcja „udostępnij czat” potrafi zdradzić więcej, niż się wydaje.
21 października doszła kolejna sprawa: według SafeDep wersja 1.107.0 popularnej biblioteki LiteLLM trafiła na PyPI ze stealerem, który zbierał m.in. klucze SSH, dane dostępowe do chmury, sekrety CI/CD i klucze do dostawców LLM, oraz z backdoorem. Atakujący mieli dane logowania GitHub CLI trzech deweloperów. PyPI usunął tę wersję jeszcze tego samego dnia, a czysta jest m.in. wersja 1.106.2.
Agent różni się od czatu tym, że wykonuje działania: czyta pliki, uruchamia komendy, wchodzi na strony. OWASP opisuje dwa główne ryzyka:
- Prompt injection. Według OWASP w wersji pośredniej (indirect) model przyjmuje polecenia „from external sources, such as websites or files”. Wystarczy README albo strona z ukrytą instrukcją, żeby agent zrobił coś, o co go nie prosiliśmy.
- Nadmierna sprawczość (tzw. „excessive agency”). OWASP wymienia trzy przyczyny: za dużo funkcji, za dużo uprawnień i za dużo autonomii. W zapowiedzi listy na 2026 rok to ryzyko awansowało na trzecie miejsce.
OWASP prowadzi też osobną listę Top 10 dla aplikacji agentowych, w której pierwsze miejsce zajmuje „Agent Goal Hijack”, czyli przejęcie celu agenta.
Złota zasada z obu list jest ta sama: najmniejsze uprawnienia, które wystarczą do zadania, i zgoda człowieka na ryzykowne działania.
Krok 1: jak ustawić uprawnienia w Claude Code?
Pokażę to na Claude Code (od zera opisałem go w poradniku Claude Code), ale ta sama logika działa w innych harnessach agentowych.
Uprawnienia ustawiamy w settings.json jako reguły allow, ask i deny. Według dokumentacji kolejność jest stała: „deny, then ask, then allow”, więc odmowa zawsze wygrywa. Na początek zablokujmy dostęp do sekretów. Ten przykład pochodzi wprost z opisu ustawień:
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(./config/credentials.json)",
"Bash(curl *)"
]
}
}
Co ważne, reguły deny mają granice i dokumentacja mówi o nich wprost:
- Nie działają na komendy, które czytają pliki bez podania nazwy, np.
grep -r pattern ., ani na dowolne podprocesy. Bash(curl *)pasuje do komendy dosłownie, więc nie zatrzyma/usr/bin/curlanish -c 'curl …'.- Plik
.claudeignorenie ma żadnego efektu, a jego wpisy trzeba przenieść do regułReadwdeny.
Dlatego reguły to pierwsza warstwa, a nie cała ochrona. Aktualne uprawnienia sprawdzimy komendą /permissions.
Druga rzecz to tryb pracy. Claude Code ma tryby default, acceptEdits, plan, auto, dontAsk i bypassPermissions. O ostatnim dokumentacja pisze: „Only use this mode in isolated environments like containers or VMs”. Na współdzielonym komputerze możemy go całkiem wyłączyć, ustawiając permissions.disableBypassPermissionsMode na "disable".
Krok 2: jak włączyć sandbox?
Sandbox to granica, którą pilnuje sam system operacyjny, więc działa tam, gdzie reguły deny nie sięgają. Według dokumentacji sandboxa jest domyślnie wyłączony. Włączamy go komendą w sesji:
/sandbox
albo ustawiając sandbox.enabled na true w ~/.claude/settings.json. Na macOS działa od razu, a na Linuksie i WSL2 potrzebuje dwóch pakietów:
sudo apt-get install bubblewrap socat
Na Windowsie bez WSL2 sandboxa nie ma, komendy idą bez izolacji.
Co daje sandbox po włączeniu:
- Komendy zapisują tylko w katalogu roboczym i plikach tymczasowych.
- Ruch sieciowy idzie przez lokalne proxy, a lista dozwolonych domen (
network.allowedDomains) na starcie jest pusta. - Czytać mogą jednak większość dysku, łącznie z
~/.sshi~/.aws/credentials. Te ścieżki trzeba zablokować samemu przezfilesystem.denyReadalbo sekcjęcredentials, bo jak czytamy, „There is no built-in credential deny list”.
Dwie uwagi z dokumentacji. Po pierwsze, sandbox obejmuje tylko komendy powłoki: narzędzia Read, Edit, Write i WebFetch, hooki oraz lokalne serwery MCP działają poza nim. Po drugie, szerokie domeny w stylu github.com na liście dozwolonych mogą otworzyć drogę do wyprowadzenia danych. Kto chce izolacji wszystkiego naraz, powinien uruchomić cały agent w kontenerze albo maszynie wirtualnej.
W Codex od OpenAI odpowiednikiem są tryby read-only, workspace-write i danger-full-access, a sieć jest domyślnie wyłączona. Flaga --yolo (alias --dangerously-bypass-approvals-and-sandbox) wyłącza i zgody, i sandbox, więc zostawmy ją na kontenery.
Krok 3: gdzie trzymać klucze API?
Najprostsza zasada: klucz nie trafia do kodu ani do repozytorium. Anthropic zaleca, żeby nie wpisywać klucza bezpośrednio w kod ani pliki konfiguracyjne i dodać pliki .env do .gitignore. OpenAI radzi przekazywać klucze przez zmienne środowiskowe albo menedżer sekretów i regularnie je rotować.
W praktyce:
- Osobne klucze na development, testy i produkcję (to też z zaleceń Anthropic). Jeden wyciek nie kładzie wtedy wszystkiego.
- Klucz dla agenta to osobny klucz z własnym limitem, a nie nasz główny.
- Po wycieku unieważniamy klucz od razu, a dopiero potem szukamy przyczyny.
Co ciekawe, GitHub sam pilnuje części wycieków. Jeśli klucz Claude trafi do publicznego repozytorium, GitHub powiadamia Anthropic, a ten automatycznie dezaktywuje klucz.
Krok 4: jak ustawić limity wydatków?
Limit nie zatrzyma wycieku, ale ograniczy rachunek, gdy klucz trafi w niepożądane ręce.
- Anthropic. W Claude Console wchodzimy na stronę Billing (
platform.claude.com/settings/billing), w sekcji Spend limits klikamy Adjust limit albo Set limit. Limity da się ustawić też na poziomie workspace’u, z wyjątkiem domyślnego. - OpenAI. W ustawieniach projektu wchodzimy w Limits, ustawiamy Monthly spend limit i włączamy Enforce a hard limit. Uwaga: alerty o wydatkach („Spend alerts do not enforce a cap”) niczego nie blokują, a sam limit działa z opóźnieniem, więc wydatki mogą go lekko przekroczyć.
Dobrym nawykiem jest jeden projekt (albo workspace) na każdego agenta, każdy z własnym kluczem i limitem.
Krok 5: jak wyłapać sekrety, zanim wyciekną?
Agenci piszą dużo kodu i chętnie robią commity, więc warto mieć automat, który zatrzyma klucz przed pushem.
- Push protection na GitHubie. Według dokumentacji blokuje pushe z sekretami, zanim trafią do repozytorium. Dla kont użytkowników jest domyślnie włączona dla publicznych repozytoriów, a na poziomie repozytorium jest domyślnie wyłączona i wymaga GitHub Secret Protection.
- Gitleaks lokalnie. Instalujemy przez
brew install gitleaksi skanujemy katalog albo historię gita (README):
gitleaks dir -v .
gitleaks git -v .
- TruffleHog sprawdza też, czy znaleziony sekret nadal działa (README). To tym narzędziem NorForge zweryfikował, że część sekretów z paneli Cairn była aktywna:
trufflehog filesystem path/to/dir
Na co zwrócić uwagę przy serwerach MCP?
Serwer MCP to kod, który działa z naszymi uprawnieniami. Dokumentacja Claude Code zaleca pisać własne serwery albo używać tylko tych od zaufanych dostawców i zaznacza, że Anthropic nie audytuje serwerów MCP.
Zalecenia bezpieczeństwa MCP (wersja robocza specyfikacji) dodają kilka konkretów:
- Klient powinien pokazać pełną komendę uruchamiającą lokalny serwer, bez skracania. Przykład ataku ze specyfikacji to niewinny
npx, za którym stoicurlwysyłający~/.ssh/id_rsana obcy serwer. - Lokalne serwery najlepiej uruchamiać w sandboxie z minimalnymi uprawnieniami i przez transport
stdio. - Serwer nie może przyjmować tokenów, które nie zostały wydane dla niego (tzw. „token passthrough” jest zabroniony).
- Uprawnienia OAuth nadajemy stopniowo, bez szerokich zakresów w stylu
*,allczyfull-access.
FAQ
Czy reguły deny w Claude Code wystarczą do ochrony pliku .env?
Nie do końca. Blokują wbudowane narzędzia i rozpoznawane komendy jak cat, ale nie grep -r ani dowolne podprocesy. Pełną ochronę na poziomie systemu daje dopiero sandbox z filesystem.denyRead.
Co zrobić, gdy klucz API wyciekł?
Unieważnić go od razu w panelu dostawcy, wygenerować nowy, podmienić go we wszystkich aplikacjach i przejrzeć ostatnie zużycie na koncie. Więcej w tekście o wycieku z OpenCode.
Czym jest prompt injection w agentach AI?
To ukryte polecenia w treściach, które agent czyta (strony, pliki, maile). Agent może je wykonać jak nasze. Dlatego ryzykowne działania powinny wymagać naszej zgody, a agent nie powinien mieć dostępu do sekretów.
Czy sandbox działa na Windowsie?
W Claude Code tylko przez WSL2. Na natywnym Windowsie komendy działają bez sandboxa.