Najmniejsze uprawnienia (least-privilege) to jedna z najstarszych i najbardziej niezawodnych idei w bezpieczeństwie. Nadaj tożsamości dokładnie taki dostęp, jakiego potrzebuje, i nic ponadto, a zasięg rażenia każdego naruszenia pozostaje niewielki. W przypadku kont użytkowników i długowiecznych kont usługowych model ten sprawdza się całkiem dobrze: role są przeglądane, nadania są ograniczone do potrzebnego zakresu, a certyfikacje dostępu odbywają się w cyklu kwartalnym.
Agenci AI po cichu rozbijają ten model. Agent otrzymuje poświadczenie, narzędzie, połączenie z serwerem MCP i od tej chwili jego zachowanie jest dynamiczne. To on decyduje w czasie działania, które zasoby odczytać, do których zapisać, które narzędzie wywołać jako następne. Nadanie, które spisano pierwszego dnia, opisuje pułap, a nie to, co agent faktycznie robi. A ponieważ agenci są produktywni, pułap ten bywa zazwyczaj hojny: szerokie role bazodanowe, dostęp do zapisu „na wszelki wypadek”, jedno konto usługowe współdzielone przez pół tuzina przepływów pracy. W efekcie powstaje środowisko, w którym dostęp nadany i dostęp faktycznie wykorzystywany rozjeżdżają się, po cichu, każdego dnia.
Niezależne badania branżowe oddają skalę tego ślepego punktu: około 82% organizacji zgłasza, że działają u nich agenci AI, o których istnieniu nie wiedziały, podczas gdy zaledwie około 21% prowadzi ich inwentaryzację w czasie rzeczywistym (CSA/Token Security, n=418). Nie da się egzekwować najmniejszych uprawnień w środowisku, którego się nie widzi.
Definicja dryfu najmniejszych uprawnień
Nazwijmy tę rzecz precyzyjnie. Dryf najmniejszych uprawnień to rosnąca różnica między dostępem, który agentowi nadano, a dostępem, który u niego zaobserwowano. Ma on dwa kierunki awarii i tylko jeden z nich jest oczywisty.
Kierunkiem oczywistym jest niewykorzystanie: agent posiada dostęp do zapisu w tabeli, do której nigdy nic nie zapisał. To martwe uprawnienie i ryzyko, które ponosisz bez żadnej korzyści. Kierunkiem niebezpiecznym jest odwrotny sygnał, który z tego wynika: gdy zbiór zaobserwowany zawiera coś, czego zbiór nadany nigdy świadomie nie przyznał, mamy do czynienia z działaniem, którego nikt nie przejrzał. Zadanie eksportu, które nagle zapisuje do kubełka, z którego dotąd jedynie odczytywało. Agent, którego polityka ograniczyła do jednego schematu, sięgający do innego. To nie są przypadki egzotyczne; to codzienna tkanka agentów połączonych ze sobą za pomocą zbyt szerokich nadań.
Powód, dla którego jest to trudne, i powód, dla którego dotyczy to agentów, a nie ludzi, jest taki, że zachowanie jest generowane, a nie konfigurowane. Człowiek z nadmiernym dostępem w większości przypadków z niego nie korzysta. Agent z nadmiernym dostępem wykorzysta wszystko, co pomoże mu wykonać postawione przed nim zadanie, łącznie ze ścieżkami, których nikt nie przewidział. Statyczny przegląd polityki nie nadąża za zachowaniem, które zmienia się przy każdym uruchomieniu.
Zamiana dryfu w sygnał możliwy do przeglądu
Dryf jest groźny tylko dopóty, dopóki pozostaje niewidoczny. Zadanie polega na uczynieniu z niego sygnału, który człowiek może przejrzeć, a to wymaga współdziałania dwóch elementów: nieprzerwanej obserwacji tego, czego agenci faktycznie dotykają, oraz stabilnego zapisu tego, co wolno im było dotknąć.
Obserwacja musi działać w trybie read-first. Kolektor, który obserwuje na podstawie logów, śladów OpenTelemetry i sygnałów jądra eBPF, znajduje się poza ścieżką danych agenta. Nie jest proxy, nie bramkuje wywołań, a jeśli ulegnie awarii, to zawodzi w sposób bezpieczny (fail open): agent działa dalej, a ty tracisz widoczność, a nie dostępność. Ta asymetria ma znaczenie: mechanizm bezpieczeństwa, który może położyć produkcję, to mechanizm, który zespoły po cichu wyłączają. Warstwa eBPF działa w szczególności jako prawda absolutna na poziomie jądra (kernel-level ground truth), czyli ta część, której agent nie może obejść — i dlatego wskazówki na poziomie protokołu, takie jak adnotacje narzędzi MCP (readOnlyHint, destructiveHint), są z nią weryfikowane krzyżowo, a nie traktowane jako wiarygodne. Sama specyfikacja MCP mówi, że te adnotacje są niezaufane; to sygnały jądra sprawiają, że weryfikacja krzyżowa staje się realna.
Tym, co produkuje obserwacja, jest mapa dostępu: dla każdego agenta — do których zasobów sięgnął oraz czy odczytywał (R), czy odczytywał/zapisywał (RW). Mapa przechowuje relacje dostępu, a nie ładunki danych, sekrety ani dane osobowe. Najciekawsza jest różnica:
| Agent | Zasób | Nadane | Zaobserwowane | Dryf |
|---|---|---|---|---|
| data-export-job | prod-postgres | R | R | brak |
| data-export-job | s3://billing-exports | R | RW | nieprzejrzany zapis |
| report-builder | analytics-db | R | (niewykorzystane) | martwe uprawnienie |
Wierszem, który ma znaczenie, jest ten środkowy. Polityka nadała odczyt na kubełku eksportu; kolektor zaobserwował zapis. Ta jedna linia to sztandarowe ryzyko, które dryf najmniejszych uprawnień ma ujawniać: uprawnienie wykorzystane, którego nikt nie przejrzał, przypisane do konkretnego agenta, a nie do współdzielonego konta usługowego — ponieważ to właśnie tożsamość przypisana do pojedynczego agenta sprawia, że atrybucja i audyt są w ogóle możliwe.
Egzekwowanie w momencie dostępu, a nie tylko logowanie
Wykrywanie mówi ci, że dryf wystąpił. Aby domknąć pętlę, chcesz, by nieprzejrzany zapis był ścieżką zablokowaną, a nie zalogowaną. I tu wkracza policy-as-code oceniane w momencie dostępu. Ta sama różnica, która oznaczyła dryf, staje się regułą, która mu zapobiega.
Rozważ przypięcie zadania eksportu do trybu tylko do odczytu na produkcyjnej bazie danych i jednoznaczne odrzucanie zapisów, z naruszeniem, które blokuje i alarmuje, zamiast przechodzić w ciszy:
agent "data-export-job" {
# Tylko do odczytu w bazie danych operacyjnej. Brak zapisów w ogóle.
access "prod-postgres" {
mode = "read"
deny = ["write", "delete", "ddl"]
}
# Docelowy zasób eksportu, którego zadanie *powinno* używać.
access "s3://billing-exports" {
mode = "read"
}
on_violation {
action = "block" # odmów w momencie dostępu
alert = "security-oncall"
audit = "append" # dopisz do dziennika audytu odpornego na manipulacje
}
}
Prześledźmy konkretnie stan przed i po.
Przed. Zadanie eksportu, posiadające szeroką rolę, wystawia zapis do s3://billing-exports. Nic go nie zatrzymuje. Działanie kończy się powodzeniem, wtapia się w normalny ruch i pojawia się dni później, o ile w ogóle, jako anomalia na mapie dostępu. Różnica między uprawnieniami nadanymi a zaobserwowanymi powiększyła się, a jedynym artefaktem jest linia w logu, której nikt nie przeczytał.
Po. Nadchodzi ten sam zapis. Polityka jest oceniana w momencie dostępu, widzi write na zasobie ograniczonym do read i zwraca odmowę, zanim operacja dojdzie do skutku. Naruszenie blokuje wywołanie, podnosi alert do dyżuru on-call i dopisuje wpis do tylko-dopisywalnego (append-only), połączonego łańcuchem skrótów dziennika audytu. Nieprzejrzany zapis nigdy nie staje się nieprzejrzaną zmianą. Dryf zostaje przekształcony, w tej samej chwili, z powrotem w ścieżkę zgodną z najmniejszymi uprawnieniami.
Dwie właściwości pozwalają zachować uczciwość tego rozwiązania. Po pierwsze, każdy uprzywilejowany wgląd w mapę dostępu sam podlega audytowi — kto co oglądał — ponieważ mapa jest wrażliwa, a narzędzie bezpieczeństwa, które nie potrafi rozliczyć własnych operatorów, nie jest godne zaufania. Po drugie, poziom pewności jest pokazywany wprost: działanie przypisane agentowi na podstawie dowodów z poziomu jądra jest oznaczane inaczej niż takie, które wywnioskowano w przybliżeniu. Nigdy nie zostaniesz poproszony o działanie na podstawie sfabrykowanej pewności.
Wniosek
Najmniejsze uprawnienia nie zawiodły w przypadku agentów AI; zawiódł cykl przeglądów. Nadania są zbyt szerokie, zachowanie jest dynamiczne, a kwartalne certyfikacje nie są w stanie śledzić powierzchni dostępu, która zmienia się przy każdym uruchomieniu. Rozwiązaniem nie jest cięższe proxy na ścieżce krytycznej. Jest nim nieprzerwana obserwacja w trybie read-first, która produkuje porównanie uprawnień nadanych z zaobserwowanymi, oraz policy-as-code, które egzekwuje skorygowaną granicę w momencie dostępu — tak aby nadmiernie uprzywilejowany agent został wychwycony jako sygnał możliwy do przeglądu na długo zanim przerodzi się w incydent.
Jeśli chcesz zobaczyć, jak kolektor, mapa dostępu i egzekwowanie w momencie dostępu współgrają ze sobą bez tkwienia na ścieżce danych Twoich agentów, strona architektura prowadzi przez projekt rozwiązania, a produkt pokazuje, jak widok uprawnień nadanych w zestawieniu z zaobserwowanymi wygląda w realnym środowisku.