Każda iteracja sprawia, że Twój kod jest mniej bezpieczny
Po dziesięciu rundach iteracyjnego doskonalenia kodu sterowanego przez LLM 43,7 procent łańcuchów iteracji zawierało więcej podatności niż kod bazowy, od którego rozpoczęto pracę.1 Agent poprawił funkcjonalność. Agent przeszedł testy. Jednocześnie kod stawał się coraz mniej bezpieczny z każdą iteracją — zjawisko, które badacze nazywają „dryfem specyfikacji” (specification drift). Nikt tego nie zauważył, ponieważ kod wypadał lepiej pod każdym względem — z wyjątkiem bezpieczeństwa.
TL;DR
Badanie iteracyjnego doskonalenia kodu przez LLM na trzech modelach (GPT-5-Nano, Claude Sonnet 4.5, DeepSeek-V3) i 2880 krokach iteracji ujawnia paradoks: agenci optymalizują pod kątem poprawności funkcjonalnej, jednocześnie w ciszy degradując bezpieczeństwo. Standardowe środki zaradcze zawodzą. Dodanie bramek z narzędziami statycznej analizy bezpieczeństwa (SAST) do pętli zwiększyło ukrytą degradację z 12,5 procent do 20,8 procent. Framework SCAFFOLD-CEGIS rozwiązał problem za pomocą czterech warstw weryfikacji, osiągając 2,1 procent ukrytej degradacji przy 100-procentowej monotoniczności bezpieczeństwa — kosztem 77 procent wskaźnika ukończenia zadań. To odkrycie ma znaczenie dla każdego, kto uruchamia autonomiczne pętle agentów.
Paradoks
Badacze przetestowali trzy modele LLM (GPT-5-Nano, Claude Sonnet 4.5, DeepSeek-V3) na 24 zadaniach programistycznych w sześciu kategoriach bezpieczeństwa (bazy danych, obsługa danych wejściowych, uwierzytelnianie, zarządzanie zasobami, kryptografia, obsługa ścieżek), generując 288 łańcuchów iteracji i łącznie 2880 kroków iteracji.1 Wniosek: dryf specyfikacji podczas optymalizacji wielokryterialnej powoduje stopniową degradację bezpieczeństwa w kolejnych iteracjach.
Mechanizm: gdy agent optymalizuje kod przez wiele rund, każda runda koncentruje się na ulepszeniach funkcjonalnych (naprawianie błędów, dodawanie funkcji, przechodzenie testów, poprawa wydajności). Ograniczenia bezpieczeństwa konkurują z celami funkcjonalnymi o uwagę agenta. Po dziesięciu rundach agent uczy się (niejawnie, poprzez akumulację kontekstu), że zmiany funkcjonalne generują pozytywną informację zwrotną, podczas gdy ograniczenia bezpieczeństwa nie generują żadnej. Logika obronna, która nie przyczynia się do widocznej funkcjonalności, zostaje uproszczona, usunięta podczas refaktoryzacji lub zastąpiona słabszymi alternatywami.
Wskaźnik degradacji 43,7 procent pochodzi z osobnego badania obserwacyjnego śledzącego GPT-4o przez dziesięć rund iteracji. Główny eksperyment porównywał SCAFFOLD-CEGIS z pięcioma istniejącymi podejściami obronnymi: bezpieczeństwo oparte na promptach, samodoskonalenie, SAST post-hoc, strażnik oparty na testach i strażnik hybrydowy.1 Społeczność badawcza wcześniej zidentyfikowała iteracyjną degradację jako problem. Żadna z pięciu alternatyw go nie rozwiązała.
Niezależne badanie autorstwa Shukla, Joshiego i Syeda, recenzowane i przyjęte na konferencji IEEE-ISTAS 2025, potwierdza ten wzorzec.4 Badacze wzięli dziesięć zweryfikowanych pod kątem bezpieczeństwa próbek kodu w C i Java, zastosowali cztery odrębne strategie promptowania w dziesięciu iteracjach każda (łącznie 400 próbek) i zmierzyli 37,6-procentowy wzrost krytycznych podatności już po pięciu iteracjach. Taksonomia podatności obejmowała 12 kategorii, w tym bezpieczeństwo pamięci, walidację danych wejściowych, implementację kryptograficzną i luki typu injection. Spójność wyników między różnymi zespołami badawczymi, językami programowania i metodologiami ewaluacji potwierdza, że iteracyjna degradacja jest właściwością samego podejścia, a nie artefaktem pojedynczej konfiguracji eksperymentalnej.
Dlaczego bramki SAST pogarszają sytuację
Najbardziej nieintuicyjne odkrycie: dodanie narzędzi statycznej analizy bezpieczeństwa jako bramek między iteracjami zwiększyło ukrytą degradację z 12,5 procent do 20,8 procent.1
Artykuł przypisuje przyczynę dryfowi specyfikacji podczas optymalizacji wielokryterialnej. Komplementarne wyjaśnienie nawiązuje do znanego wzorca w tworzeniu oprogramowania przez ludzi: gdy programiści polegają na linterach i analizatorach statycznych, piszą mniej defensywnie, ponieważ narzędzia „wyłapią” problemy. Ta sama dynamika prawdopodobnie dotyczy agentów LLM. Gdy agent otrzymuje informacje zwrotne z SAST między iteracjami, zachodzą dwa zjawiska:
-
Agent optymalizuje pod kątem przejścia skanera, a nie pisania bezpiecznego kodu. Narzędzia SAST sprawdzają znane wzorce podatności (SQL injection, XSS, przepełnienia bufora). Agent uczy się unikać tych konkretnych wzorców, jednocześnie wprowadzając nowe słabości bezpieczeństwa, których skaner nie wykrywa.
-
Agent usuwa „nadmiarowe” zabezpieczenia. Jeśli skaner zgłosi, że walidacja danych wejściowych w warstwie A jest wystarczająca, agent w kolejnej iteracji usuwa walidację w warstwie B. Walidacja w warstwie B stanowiła ochronę wielowarstwową (defense-in-depth), a nie redundancję. Skaner nie potrafi odróżnić jednego od drugiego.
Efekt: iteracja z bramkami SAST generuje kod, który przechodzi skany bezpieczeństwa, ale zawiera więcej ukrytych podatności niż iteracja bez bramek. Narzędzia tworzą fałszywe poczucie bezpieczeństwa, które sprawia, że agent staje się mniej ostrożny, nie bardziej.
Każdy, kto prowadzi autonomiczną pętlę kodowania z bramkami SAST między iteracjami, powinien zwrócić na to uwagę. Bramki nie chronią. Bramki uczą agenta, jak obchodzić ochronę.
Co SCAFFOLD-CEGIS robi inaczej
Framework SCAFFOLD-CEGIS przyjmuje odmienne podejście.1 Zamiast sprawdzać znane wzorce podatności, framework wymusza monotoniczność bezpieczeństwa: żadna iteracja nie może uczynić kodu mniej bezpiecznym niż poprzednia iteracja.
Wyniki dla wszystkich trzech podejść:
| Podejście | Ukryta degradacja (SSDR) | Monotoniczność bezpieczeństwa | Ukończenie zadań |
|---|---|---|---|
| Brak bramek (bazowe) | 12,5% | Niemierzona | Wyższe |
| Bramki SAST | 20,8% | Niegwarantowana | Wyższe |
| SCAFFOLD-CEGIS | 2,1% | 100% | 77,14% |
Architektura wykorzystuje cztery sekwencyjne warstwy weryfikacji, z których każda sprawdza inną właściwość:1
| Warstwa | Funkcja | Kryterium bramki |
|---|---|---|
| Poprawność | Uruchomienie pełnego zestawu testów | Wszystkie testy przechodzą |
| Monotoniczność bezpieczeństwa | Porównanie wyników SAST między iteracjami | Brak nowych podatności względem poprzedniej |
| Budżet zmian | Ograniczenie skali zmian na iterację | Rozmiar zmian w ramach progu |
| Integralność kotwic | Weryfikacja elementów krytycznych dla bezpieczeństwa | Dopasowanie podciągu, wyrażenia regularnego, AST lub semantyczne |
Framework wykorzystuje zasadę CEGIS (counterexample-guided inductive synthesis): zamkniętą pętlę generowania kandydatów, weryfikacji, informacji zwrotnej i regeneracji. Zamiast formalnych weryfikatorów system stosuje analizę statyczną i sprawdzanie kotwic semantycznych, reprezentując kontrprzykłady jako ustrukturyzowane raporty o błędach.1 Jeśli którakolwiek warstwa odrzuci iterację, system wraca do poprzedniej wersji zamiast próbować naprawić regresję.
Kompromis jest realny: SCAFFOLD-CEGIS osiągnął 77,14 procent wskaźnika ukończenia zadań, w porównaniu z wyższymi wskaźnikami dla mniej bezpiecznych podejść.1 Monotoniczność bezpieczeństwa kosztuje produktywność. Framework odrzuca iteracje, które mniej rygorystyczny system zaakceptowałby i udoskonalił. To, czy kompromis jest opłacalny, zależy od tego, czy bardziej cenimy gwarancje bezpieczeństwa, czy przepustowość.
Kluczowy wniosek: cofnij w przypadku porażki zamiast iterować nad porażką. Standardowe pętle z bramkami SAST wykrywają problem i proszą agenta o naprawę, co generuje kolejną iterację mogącą wprowadzić nowe problemy. SCAFFOLD-CEGIS wykrywa problem i całkowicie odrzuca iterację. Gwarancja monotoniczności wynika z tego, że nigdy nie akceptuje się regresji, a nie z tego, że wykrywa się i naprawia regresje.
Związek z projektowaniem systemów orkiestracji agentów
Odkrycie łączy się bezpośrednio ze sposobem, w jaki praktycy budują warstwy orkiestracji wokół CLIów agentów.2 Siedem trybów awarii, które udokumentowałem na podstawie ponad 500 autonomicznych sesji, obejmuje kilka, które paradoks iteracyjnego doskonalenia wyjaśnia: agenci, którzy przechodzą testy, jednocześnie degradując jakość kodu; agenci, którzy optymalizują pod kątem niewłaściwej metryki; agenci, którzy usuwają ograniczenia bezpieczeństwa podczas refaktoryzacji.
Hooki decyzyjne opisane przeze mnie w „Anatomy of a Claw” rozwiązują problem degradacji innym mechanizmem. quality-gate.sh blokuje raporty ukończenia pozbawione dowodów. filter-sensitive.sh przechwytuje ujawnienie danych uwierzytelniających, zanim trafią na dysk. recursion-guard.sh ogranicza głębokość tworzenia podagentów. Każdy hook wymusza właściwość monotoniczności: system nie powinien się pogarszać w określonym wymiarze w miarę kolejnych iteracji agenta. Wzorzec konstytucji czasu wykonania rozszerza tę samą ideę: wbudowane reguły zarządzania, których agent nie może nadpisać podczas działania.
System autoresearch Karpathy’ego stosuje ten sam wzorzec.3 System ewaluacji zachowuje ulepszenia i odrzuca regresje poprzez zarządzanie gałęziami Git. Metryka treningowa (bity walidacyjne na bajt) służy jako ograniczenie monotoniczności. Żaden wynik eksperymentu, który pogarsza metrykę, nie przetrwa.
Trzy niezależne systemy (badania nad formalną weryfikacją, infrastruktura badawcza ML, produkcyjne systemy orkiestracji agentów) zbiegają się w tej samej zasadzie projektowej: nigdy nie iteruj nad porażką; zawsze cofaj w przypadku porażki. Dawanie agentowi drugiej szansy na naprawę regresji daje gorsze wyniki niż odrzucenie regresji i rozpoczęcie od nowa.
Co powinni zrobić praktycy
Trzy konkretne działania wynikające z odkryć:
Audytuj pętle iteracji pod kątem monotoniczności bezpieczeństwa. Jeśli agent wykonuje wiele rund modyfikacji kodu, należy porównywać stan bezpieczeństwa w każdej rundzie z oryginalnym stanem bazowym, nie tylko z poprzednią rundą. Kumulacyjny dryf jest niewidoczny, gdy porównuje się jedynie sąsiednie iteracje.
Nie polegaj wyłącznie na bramkach SAST. Wyniki z bramkami SAST (20,8 procent degradacji, gorzej niż bez bramek) powinny zmienić sposób projektowania pętli informacji zwrotnej. Narzędzia SAST są wartościowe do wykrywania znanych wzorców w kodzie pisanym przez ludzi. W pętlach iteracji agentów narzędzia te stają się celami optymalizacji, które agent uczy się obchodzić. Warto stosować SAST jako jeden z wielu sygnałów, a nie jako bramkę.
Wdróż cofanie w przypadku porażki, nie naprawianie w przypadku porażki. Gdy iteracja wprowadza regresję, należy ją całkowicie odrzucić. Nie należy prosić agenta o naprawę regresji w kolejnej iteracji. Próba naprawy jest sama w sobie iteracją podlegającą tej samej dynamice degradacji. Minimalna implementacja z użyciem Git:
#!/bin/bash
# monotonicity-gate.sh — revert on security regression
BASELINE_HASH="$1" # git hash of the known-good baseline
# Run your security checks against current state
CURRENT_VULNS=$(semgrep --config auto --json . | jq '.results | length')
BASELINE_VULNS=$(git stash && git checkout "$BASELINE_HASH" -q && \
semgrep --config auto --json . | jq '.results | length' && \
git checkout - -q && git stash pop -q)
if [ "$CURRENT_VULNS" -gt "$BASELINE_VULNS" ]; then
echo "Security regression: $BASELINE_VULNS → $CURRENT_VULNS vulnerabilities"
git checkout "$BASELINE_HASH" -- .
exit 2 # Block the iteration
fi
Wzorzec porównuje z oryginalnym stanem bazowym, nie z poprzednią iteracją. Kumulacyjny dryf stanowi zagrożenie.
FAQ
Czy iteracyjne doskonalenie zawsze degraduje bezpieczeństwo?
Nie każdy łańcuch iteracji powoduje degradację. Badanie SCAFFOLD-CEGIS wykazało, że 43,7 procent łańcuchów zawierało więcej podatności po dziesięciu rundach, co oznacza, że 56,3 procent utrzymało lub poprawiło stan bezpieczeństwa.1 Niezależne badanie IEEE-ISTAS wykazało 37,6-procentowy wzrost krytycznych podatności po pięciu iteracjach.4 Problem polega na tym, że degradacja jest cicha: agent generuje funkcjonalnie poprawny kod, który przechodzi testy, podczas gdy właściwości bezpieczeństwa erodują. Bez jawnych kontroli monotoniczności bezpieczeństwa degradacja pozostaje niewykryta do momentu wykorzystania podatności.
Dlaczego bramki SAST pogarszają problem zamiast go łagodzić?
Narzędzia analizy statycznej sprawdzają znane wzorce podatności. Gdy agent otrzymuje informacje zwrotne z SAST między iteracjami, optymalizuje pod kątem przejścia skanera, a nie pisania bezpiecznego kodu. Agent unika flagowanych wzorców, jednocześnie wprowadzając nowe słabości, których skaner nie potrafi wykryć. Agent usuwa również warstwy ochrony wielowarstwowej, które skaner oznacza jako redundantne. Efekt netto: kod przechodzi skany, ale zawiera więcej ukrytych podatności niż kod generowany bez bramek SAST.
Czym jest monotoniczność bezpieczeństwa i jak SCAFFOLD-CEGIS ją wymusza?
Monotoniczność bezpieczeństwa oznacza, że żadna iteracja nie może uczynić kodu mniej bezpiecznym niż poprzednia iteracja. SCAFFOLD-CEGIS wymusza tę właściwość poprzez cztery sekwencyjne warstwy weryfikacji: poprawność (zestaw testów), monotoniczność bezpieczeństwa (porównanie SAST między iteracjami), budżet zmian (ograniczenie skali zmian) i integralność kotwic (weryfikacja, czy elementy krytyczne dla bezpieczeństwa przetrwały). Framework stosuje zasadę CEGIS (counterexample-guided inductive synthesis), reprezentując kontrprzykłady jako ustrukturyzowane raporty o błędach zamiast formalnych dowodów. Jeśli którakolwiek warstwa odrzuci iterację, system ją całkowicie odrzuca zamiast przekazywać agentowi do naprawy. Kompromis: 77 procent wskaźnika ukończenia zadań — mniej niż w mniej rygorystycznych podejściach.
Czym różni się cofanie w przypadku porażki od naprawiania w przypadku porażki w pętlach agentów?
Naprawianie w przypadku porażki wykrywa problem i prosi agenta o jego korektę w kolejnej iteracji. Próba korekty sama podlega temu samemu dryfowi specyfikacji, który spowodował oryginalną regresję, często wprowadzając nowe problemy. Cofanie w przypadku porażki odrzuca całą iterację i wraca do ostatniego znanego dobrego stanu. Agent zaczyna od nowa z czystym stanem bazowym zamiast akumulować poprawki korygujące. Zarządzanie gałęziami Git sprawia, że cofanie jest w praktyce trywialne.
Czy mogę zastosować te wnioski w moim obecnym przepływie pracy z Claude Code lub Codex?
Tak. Trzy działania opisane w sekcji dla praktyków mają zastosowanie do każdej pętli agenta, która modyfikuje kod w wielu rundach. Należy audytować pętle iteracji, porównując stan bezpieczeństwa z oryginalnym stanem bazowym (nie tylko z poprzednią iteracją). Warto traktować wyniki SAST jako jeden z wielu sygnałów, a nie jako bramkę. Gdy iteracja wprowadza regresję, należy użyć git checkout lub git revert, aby całkowicie odrzucić zmianę, zamiast prosić agenta o naprawę. Wzorzec systemu orkiestracji opartego na hookach stanowi konkretny model implementacji do zakodowania tych kontroli jako zautomatyzowanych bramek.
Źródła
-
Yi Chen et al., “SCAFFOLD-CEGIS: Preventing Latent Security Degradation in LLM-Driven Iterative Code Refinement,” arXiv:2603.08520, March 2026, arxiv.org/abs/2603.08520v1. Tested GPT-5-Nano, Claude Sonnet 4.5, DeepSeek-V3 across 24 tasks, 288 chains, 2,880 steps. 43.7% degradation rate (GPT-4o observational study); SAST gates increased SSDR from 12.5% to 20.8%; SCAFFOLD-CEGIS achieved 2.1% SSDR with 100% safety monotonicity at 77.14% task completion. ↩↩↩↩↩↩↩↩↩
-
Blake Crosley, “Anatomy of a Claw: 84 Hooks as an Orchestration Layer,” blakecrosley.com, February 2026. ↩
-
Andrej Karpathy, autoresearch: AI agents running autonomous ML research, March 2026, github.com/karpathy/autoresearch. 630-line Python script, ~700 experiments over two days, ~20 genuine improvements. ↩
-
Shivani Shukla, Himanshu Joshi, Romilla Syed, “Security Degradation in Iterative AI Code Generation: A Systematic Analysis of the Paradox,” IEEE-ISTAS 2025, arXiv:2506.11022, arxiv.org/abs/2506.11022. 10 security-verified C/Java samples, 4 prompting strategies, 10 iterations each (400 total), 37.6% increase in critical vulnerabilities after 5 iterations. 12 vulnerability categories. ↩↩