Blog

Agent potrzebuje dostępu do API - czy musi znać klucz usługi?

Klucz w .env może nie trafić do gita i nadal wylądować w rozmowie z agentem. Dostęp do API można mu dać bez przekazywania poświadczenia usługi.

Ikona terminala połączona przerywaną linią z ramką z kluczem, od której ciągła linia prowadzi do niebieskiego koła z plusem, na ciemnym tle z siatką.
Spis treści

Irytuje mnie, kiedy poradnik o agentach AI pokazuje magiczną produktywność, a konfigurację dostępu do usług zamyka w zdaniu „wklej klucz do .env”. Potem agent dostaje terminal, dostęp do plików i zadanie naprawienia integracji. Ten sam plik, którego człowiek miał pilnować, staje się materiałem do diagnozy.

Uważam takie poradniki za szkodliwe, jeśli są kierowane do początkujących i nie wspominają o tym drobnym szczególe. Osoba, która właśnie uruchomiła pierwszego agenta, może nie wiedzieć, że wynik odczytu pliku trafi do modelu. Albo że dopisanie .env do .gitignore niczego tu nie zmienia.

Z drugiej strony bardziej interesuje mnie odebranie im niepotrzebnego dostępu niż apelowanie o ostrożność w poleceniu - “make no mistakes, do not leak any keys”. W moim homelabie służą do tego między innymi Infisical i Agent Vault. Pierwszy zarządza sekretami. Drugi może dołączyć klucz do żądania poza procesem agenta. Tam, gdzie potrzebuję jednej konkretnej operacji, flow pracy przewiduje jeszcze węższe uprawnienia.

Z .env do rozmowy jest krótka droga

Agent nie musi zostać zaatakowany, żeby ujawnić sekret. Odczyt dostępnej konfiguracji, zrzut środowiska procesu albo zbyt szczegółowy log mogą wystarczyć. Jeżeli narzędzie zwróci klucz, a harness przekaże ten wynik modelowi, klucz jest już w kontekście rozmowy. OWASP wymienia przypadkowe umieszczenie poświadczeń w kontekście lub logach wśród ryzyk pracy z agentami.

Przy zdalnym modelu oznacza to również wysłanie sekretu do jego dostawcy. Nie musi być to publiczny wyciek ani przejęcie konta. Nadal jednak poświadczenie trafia do miejsca, które nie potrzebuje go do wykonania zadania. Dotyczy to Claude Code, OpenCode, Pi, Hermesa i innych harnessów, jeśli ich narzędzia mają taki dostęp.

Użycie .gitignore pomaga nie dodawać plików do repozytorium. Nie zabiera prawa do ich odczytu, a chmod też niewiele zmieni, jeżeli agent działa jako właściciel pliku albo z uprawnieniami roota.

Infisical porządkuje sekrety, ale może je też przekazać agentowi

Infisical pozwala przechowywać sekrety poza katalogiem projektu i przyznawać dostęp do określonego zakresu. Jego machine identities opisują uprawnienia usług. Dzięki temu komponent potrzebujący jednego zestawu kluczy nie musi dostawać dostępu do całego sejfu.

Zamiast utrzymywać kopie .env w kolejnych katalogach, można dostarczać klucze do aplikacji podczas jej uruchamiania. Tyle że aplikacja nadal otrzymuje prawdziwe poświadczenie. Jeżeli tą aplikacją jest harness agenta, sekret przeszedł z pliku do jego środowiska i agent może go przeczytać i potem grzecznie przeprosić za wyciek. Samo usunięcie .env nie rozwiązuje więc problemu.

Osobny proces też nie wystarczy, jeżeli agent może zmienić jego kod i uruchomić go z prawdziwymi kluczami: dopisanie logowania zmiennej odtworzy tę samą drogę do wycieku. Dlatego dla integracji obsługiwanej przez brokera to broker powinien mieć tożsamość pozwalającą pobrać klucz z Infisical. Przekazanie jej agentowi zostawiłoby mu drugą drogę do sekretu.

Agent Vault dołącza poświadczenie do żądania

Agent Vault jest pośrednikiem dla ruchu HTTP. Narzędzie agenta nie łączy się z API bezpośrednio, tylko przez Agent Vault ustawiony jako proxy. Broker sprawdza, dokąd idzie żądanie. Jeśli adres pasuje do skonfigurowanej usługi, dokłada prawdziwy klucz i dopiero wtedy wysyła żądanie dalej.

agent i jego narzędzie -> Agent Vault -> API usługi
                              ^
                              |
                           Infisical

Infisical jest tu źródłem kluczy. Agent Vault pobiera z niego sekrety i trzyma u siebie ich zaszyfrowaną kopię, więc przy każdym żądaniu nie musi pytać Infisical o klucz.

Dla każdej usługi w Agent Vault zapisuję, pod jaki adres idzie ruch i gdzie wstawić klucz, na przykład w nagłówek Authorization. Program agenta często nie wystartuje bez jakiegoś klucza w konfiguracji, więc dostaje wartość zastępczą, która niczego nie otwiera. Prawdziwy nagłówek powstaje dopiero w brokerze.

Agent nie zna więc klucza do usługi, ale musi jakoś udowodnić brokerowi, że wolno mu z niej korzystać. Do tego dostaje własny token do Agent Vault. To też jest sekret, tylko o węższym zakresie: pozwala wysyłać żądania przez skonfigurowane usługi, ale nie pozwala odczytać ani zmienić zapisanych w brokerze kluczy. W dokumentacji taka rola nazywa się proxy i jest najbardziej ograniczoną z dostępnych. Jeśli ten token wycieknie, ktoś inny może wysyłać przez broker te same żądania co agent, o ile dostanie się też do brokera przez sieć.

Prawdziwe klucze są w takim razie u brokera. Jeśli broker działa na tej samej maszynie co agent, a agent może czytać jego pliki albo przejąć jego proces, to klucze nadal są w zasięgu agenta i cały układ traci sens. Dlatego u mnie broker działa w osobnym kontenerze LXC, a nie na hostach, na których pracują agenci.

Klient DeepSeek dostaje klucz, który niczego nie otwiera

Tak to wygląda przy modelach DeepSeek, z których korzystają moi agenci. Launcher agenta ustawia przed startem taką zmienną:

export DEEPSEEK_API_KEY=dummy-agent-vault

Klient wysyła tę wartość w nagłówku Authorization, ale API DeepSeek jej nie przyjmie. Żądanie idzie przez Agent Vault, który rozpoznaje host api.deepseek.com i podmienia nagłówek na prawdziwy klucz. Jeśli agent wypisze tę zmienną, zobaczy tylko dummy-agent-vault.

Nie znaczy to, że w systemie nie ma już żadnego klucza do wycieku. Pozostałe zmienne, pliki i sposoby pobierania poświadczeń trzeba sprawdzić osobno. Prawdziwy klucz zostawiony w starej kopii .env nadal będzie dostępny, nawet jeśli nowa konfiguracja korzysta już z brokera.

Po stronie Infisical dokument o izolacji w repozytorium przewiduje osobny projekt na klucze obsługiwane przez brokera i tożsamość brokera, która może je tylko czytać. W repozytorium zapisuję reguły usług i nazwy kluczy, ale nie ich wartości.

Czy to działa, sprawdzam bez wypisywania sekretu. Wysyłam to samo żądanie z wartością zastępczą dwiema drogami: bezpośrednio i przez broker. Pytam o listę modeli, bo to zapytanie niczego nie zmienia i nie zużywa tokenów. Wynik z 14 października 2026:

GET /models, bezpośrednio:          401
GET /models, przez Agent Vault:     200

Prawdziwy klucz dokłada więc dopiero broker. Reguła tej usługi obejmuje cały host api.deepseek.com, a nie wybrane ścieżki, bo ten klucz i tak działa tylko tam. Żądanie pod inny adres pójdzie dalej bez niego.

Przy kolejnych integracjach muszę wiedzieć, które korzystają z tej drogi, a które dostają klucze inaczej. Prowadzę do tego w repozytorium rejestr tras poświadczeń. Dla każdej integracji zapisuję w nim, skąd bierze klucz, czy zmiana jest dopiero w kodzie, czy już działa, i odsyłam do wyniku testu takiego jak powyższy.

Jest też ograniczenie, które świadomie zaakceptowałem. Moi agenci korzystają z jednego wspólnego vaulta w Agent Vault, więc każdy z nich może użyć każdej skonfigurowanej w nim usługi, także tej z kluczem do DeepSeek. A za każde zapytanie do modelu płacę. Broker pilnuje tylko tego, dokąd trafia klucz: wyłącznie do api.deepseek.com. Osobne tokeny dla poszczególnych agentów pomogłyby ustalić, kto wysłał żądanie, i odciąć jednego z nich, ale nie zabrałyby im dostępu do pozostałych usług w tym vaulcie.

Które drogi do klucza zamyka każde z rozwiązań

.gitignore

1z 3 dróg

  • plik .env nie trafia do repozytorium
  • agent nadal czyta plik .env
  • agent nadal czyta zmienne środowiska

Infisical przy starcie

2z 3 dróg

  • plik .env nie trafia do repozytorium
  • nie ma pliku .env do przeczytania
  • agent nadal czyta zmienne środowiska

Agent Vault

3z 3 dróg

  • plik .env nie trafia do repozytorium
  • nie ma pliku .env do przeczytania
  • w zmiennych jest tylko wartość zastępcza

Żadne z nich nie ogranicza tego, co agent zrobi kluczem w API.

Na podstawie konfiguracji opisanej w tym wpisie. „Zamyka” przy Infisical i Agent Vault zakłada, że nigdzie nie została stara kopia .env z prawdziwym kluczem. Działanie Agent Vault sprawdzone testem z 14 października 2026.

Czasem lepiej udostępnić jedną operację niż całe API

Broker nie jest u mnie pierwszym wyborem. Jeśli agent potrzebuje jednej konkretnej operacji, wolę dać mu małą usługę, która umie zrobić tylko to. Agent Vault zostaje głównie dla szerszych API.

Taka usługa sama trzyma swój klucz. Agent może ją poprosić tylko o operacje z ustalonej listy i podać do nich parametry, a w odpowiedzi dostaje wynik. Usługa sama sprawdza, czy żądanie mieści się w zakresie i czy wymaga czyjejś zgody. Przy operacjach o dużym wpływie ta kontrola ma działać poza modelem, żeby nie zależała od tego, co model uzna za rozsądne.

MCP może udostępniać taki wąski interfejs, ale samo użycie MCP niczego nie ogranicza. Narzędzie, które przyjmuje dowolny adres, dowolne polecenie i nazwę sekretu, nadal daje agentowi szeroki dostęp. Podobnie lokalny serwer MCP z kluczem w pliku, który agent może przeczytać, niczego nie oddziela.

Sam plik z sekretami nie jest problemem. Może być częścią poprawnej konfiguracji, jeśli czyta go wydzielona usługa, a agent nie ma do niego dostępu i nie może przejąć procesu tej usługi. Ryzyko pojawia się wtedy, gdy agent może przeczytać jego zawartość.

Schowanie klucza nie odbiera uprawnień

Agent nie musi znać klucza administracyjnego, żeby narobić szkód. Wystarczy, że broker pozwala mu tego klucza używać. Dlatego nadal potrzebne są klucze z wąskimi uprawnieniami u dostawcy, rozdzielone środowiska i osobne zatwierdzanie niebezpiecznych operacji.

Dopasowanie adresu tego nie zastąpi. Według dokumentacji Agent Vault reguły usług patrzą na host i ścieżkę, a nie na metodę HTTP ani treść żądania. Jeśli broker przepuszcza ruch do danego API z kluczem, to przepuszcza i odczyt, i zapis, i usuwanie.

Osobna sprawa to żądania pod adresy, których broker nie zna. Domyślnie Agent Vault przepuszcza je dalej, tylko bez dokładania klucza. Ustawienie unmatched_host_policy=deny sprawia, że broker takie żądania odrzuca.

Samo ustawienie zmiennej HTTPS_PROXY też nie zmusza programów do korzystania z brokera. To wskazówka, którą program może zignorować. Dokumentacja nazywa domyślny tryb uruchamiania agenta przez Agent Vault kooperatywnym, czyli działającym, dopóki agent współpracuje. Agent może wyczyścić zmienne środowiskowe, uruchomić proces, który ich nie dostanie, otworzyć połączenie sieciowe z pominięciem obsługi proxy albo wysłać dane w zapytaniach DNS. Żeby zablokować bezpośrednie połączenia, potrzebne są reguły sieciowe. Ich działanie trzeba sprawdzić, próbując połączyć się z pominięciem proxy.

Żeby dopisać nagłówek, Agent Vault musi widzieć treść żądania. Rozszyfrowuje więc połączenie HTTPS od klienta i nawiązuje własne połączenie z usługą. Klient musi w tym celu ufać certyfikatowi brokera. Wyłączenie sprawdzania certyfikatów nie jest rozwiązaniem. Dokumentacja bezpieczeństwa ostrzega też, że w standardowej konfiguracji token agenta do brokera, wysyłany w nagłówku Proxy-Authorization, idzie między klientem a brokerem otwartym tekstem. Ten odcinek musi więc przebiegać przez zaufaną sieć albo szyfrowany tunel, na przykład VPN.

Odcięcie brokera od Infisical nie unieważnia kluczy, które już pobrał, bo broker trzyma ich kopię. Jeśli klucz wycieknie, trzeba go unieważnić u dostawcy usługi. Przy planowej wymianie klucza trzeba też sprawdzić, czy broker pobrał nową wartość i czy ona działa. Sam wpis nowego klucza do Infisical to za mało.

Broker to też kolejna usługa, którą trzeba aktualizować, monitorować i umieć odtworzyć po awarii. Jeśli agent w projekcie w ogóle nie potrzebuje dostępu do prawdziwego API, nie zaczynałbym od budowania takiej infrastruktury.

Na początek odbierz dostęp, którego agent nie potrzebuje

Do napisania integracji często wystarczą dokumentacja API, przykładowe odpowiedzi i plik .env.example bez sekretów. Test z prawdziwą usługą można zrobić osobno. Jeśli agent może zmieniać testowany kod, przed uruchomieniem go z prawdziwymi kluczami trzeba przejrzeć ten kod, a potem wyniki.

Skanowanie repozytorium w poszukiwaniu sekretów i filtrowanie tego, co zwracają narzędzia, może wyłapać część przypadkowych wycieków, ale nie opierałbym na tym całej ochrony. Repozytorium może być czyste, a sekret już siedzieć w rozmowie.

Gdy agent naprawdę potrzebuje dostępu podczas pracy, zacząłbym od jednej integracji i klucza testowego z małymi uprawnieniami. Sprawdziłbym dla niej:

  • czy prawdziwy klucz leży poza plikami i procesami, do których agent ma dostęp;
  • czy dozwolone żądanie z wartością zastępczą przechodzi przez broker, a wysłane bezpośrednio dostaje odmowę;
  • czy broker odrzuca token agenta, który nie ma dostępu do danego vaulta;
  • czy żądanie pod nieznany adres jest blokowane, jeśli włączyłem unmatched_host_policy=deny;
  • czy po odebraniu agentowi tokena do brokera dostęp naprawdę się kończy;
  • czy po przejściu na broker nie została gdzieś stara kopia klucza albo zapasowa droga do jego pobrania.
Wróć do bloga