CounterProof

Ustalenie to nie wyrok

AI potrafi dziś wygenerować tysiące ustaleń o podatnościach w jedno popołudnie. Ustalenie jest świadkiem, nie wyrokiem — a jedyne pole, którego nikt nie może sprawdzić, to właśnie to, które wszyscy zawyżają. Oto jak czytać powódź, nie tonąc w niej.

W około 108 godzin czasu maszynowego, w sierpniu 2026 r., jedna kampania wolontariuszy przepuściła model o otwartych wagach przez 501 projektów open source ekosystemu Bitcoina i zarejestrowała 7 958 potencjalnych ustaleń bezpieczeństwa, z czego 1 280 sklasyfikowanych jako wysokie lub krytyczne. O tej kampanii — i o rozporządzeniu, z którym się zderza — pisaliśmy w Maszyny czytają kod. Ta notatka jest o samej liczbie.

Bo pewien dostawca zabezpieczeń opublikował benchmark zestawiający trzy systemy przeglądu kodu oparte na AI z prywatną aplikacją testową: jeden znalazł 68 z 89 podłożonych podatności, drugi 60, trzeci 58. Dostawcy konkurują teraz tym stosunkiem — więcej ustaleń, taniej. Znajdowanie stało się towarem w wojnie cenowej.

Warto więc powiedzieć wprost, czym ustalenie naprawdę jest — bo ta rachuba mierzy niewłaściwą rzecz.

Ustalenie jest świadkiem, nie wyrokiem

Filologia rozstrzygnęła to pięć wieków temu, a jej słowo jest dokładne.

Gdy starożytny tekst przetrwał w wielu ręcznie kopiowanych rękopisach, żadna kopia nie jest tekstem. Każda jest świadkiem: dokumentem pochodnym niosącym oryginał — plus potknięcia, nawyki i odziedziczony dryf swojego kopisty. Zgodność trzech rękopisów może znaczyć, że lekcja jest autentyczna — albo że wszystkie trzy pochodzą od tego samego wadliwego wzorca. Dyscyplina, która to porządkuje, wytwarza edycję krytyczną: tekst ustalony najlepiej, jak się da, z aparatem pod spodem, odnotowującym każdego zważonego świadka, każdy wariant, każdą decyzję edytorską i jej powody.

Wygenerowane przez AI ustalenie o podatności jest świadkiem dokładnie w tym sensie. Nie jest defektem. Jest raportem modelu o defekcie — rzeczywistymi właściwościami kodu zmieszanymi z nawykami modelu, jego rodowodem treningowym i promptem, który je wytworzył. Zgodność dwóch skanerów może znaczyć, że błąd jest prawdziwy — albo że oba dzielą te same martwe pola i te same szablony. Trenowane w dużej mierze na tym samym publicznym korpusie, często je dzielą. Zgodność skorelowanych świadków to dowód o świadkach, nie o kodzie.

A najciężej wywalczona reguła filologów przenosi się nietknięta: to płynna lekcja jest podejrzana. Kopiści wygładzają trudny ustęp w wygodny banał, a gładka wersja częściej jest poprawką kopisty niż słowami autora. Raport o podatności ma stały gatunek: tytuł, klasa słabości, waga, odwołanie, akapit „napastnik mógłby…". Model językowy wytwarza tę formę przekonująco — niezależnie od tego, czy defekt istnieje. Połysk nie niesie informacji o prawdzie. W tym gatunku płynność nie jest referencją. Jest tym, co trzeba sprawdzić.

Dlatego rachuba to zła jednostka. Liczy świadków, a raportuje ich jako wyroki.

Waga jest tam, gdzie raporty przesadzają

Inflacja nie jest równomierna. Skupia się w jednym punkcie, z powodu strukturalnego, który warto nazwać.

„Ta funkcja porównuje znacznik czasu w milisekundach z kolumną o dokładności sekundowej" to twierdzenie, które coś cytuje — plik, wiersz, commit. Można je otworzyć i rozstrzygnąć w minutę. „Krytyczne" nie cytuje niczego. Nie ma wiersza kodu, w którym pisze Krytyczne. Waga to osąd o osiągalności, możliwości wykorzystania i promieniu rażenia — a ponieważ nie ma kotwicy w źródle, jest dokładnie tym miejscem, gdzie płynny generator dryfuje w górę bez oporu. Dramatyczna lekcja jest łatwiejsza; każda zachęta w łańcuchu raportowania nagradza większą liczbę; i nic w artefakcie się nie opiera.

Gdy więc kampania raportuje 1 280 ustaleń „wysokich lub krytycznych", uczciwa lektura brzmi: 1 280 ustaleń, które generator tak oznaczył. Etykieta jest najmniej sprawdzalnym polem dokumentu — i to ona odwala robotę w nagłówku.

Czy są możliwe do wykorzystania? Nikt jeszcze nie powiedział

Między ustaleniem a defektem leży krok, który rachuba pomija: osąd — rozstrzygnięcie, które ustalenia są prawdziwe, które osiągalne, które mają znaczenie. Ten krok wciąż jest ludzki i nie skaluje się z generowaniem.

Najczytelniejszy publiczny pomiar tego, co się dzieje, gdy się go pominie, pochodzi z curl. Jego siedmioosobowy wolontariacki zespół bezpieczeństwa patrzył, jak odsetek potwierdzonych zgłoszeń podatności spada z ponad 15 % poniżej 5 % wraz z napływem zgłoszeń wspieranych przez AI — a każde bezpodstawne zgłoszenie wciąż kosztowało godziny obalania. Jedno przyszło w komplecie z sesjami GDB i zrzutami rejestrów dla exploita HTTP/3 w funkcji, która w curl nie istnieje. Opiekun projektu opisał obciążenie triażem jako „równoznaczne z DDoS-em" („tantamount to a DDoS"), a projekt ostatecznie zamknął program bug bounty — oświadczając, że nie widział ani jednego ważnego zgłoszenia bezpieczeństwa wytworzonego z pomocą AI.

Czytajcie tę liczbę we właściwą stronę. Nie dowodzi ona, że ustalenia AI są bezwartościowe — dowodzi, że płynność ustalenia i jego ważność są od siebie niezależne i że po usunięciu kroku osądu stosunek sygnału do szumu się zapada. Zgłoszeń przybyło i były pewniejsze siebie; odsetek przeżywających sprawdzenie spadł.

Powódź to problem bezpieczeństwa, nie uciążliwość

Kusi, by „za dużo ustaleń" odłożyć do szufladki z uciążliwościami. Błąd. Gdy generowanie ucieka osądowi, prawdziwe ustalenie nie znika — leży pogrzebane w kolejce za dwustoma prawdopodobnymi, a kolejka, której nikt nie umie rozładować, to kolejka, która ukrywa. Słowo curl — DDoS — to właściwy rejestr. Zespół tonący w pewnych siebie zgłoszeniach nie jest bezpieczniejszy od zespołu bez zgłoszeń; to zespół, którego uwagę wyczerpano na świadkach, których nikt nie wziął w krzyżowy ogień pytań.

Trzymajcie dwa alarmy osobno

Mieszają się tu dwa twierdzenia, a ich rozdzielenie to cała dyscyplina.

W agregacie zagrożenie jest realne. W starym kodzie naprawdę są ogromne ilości nienaprawionych defektów, a tani, niezmordowany poszukiwacz część z nich wydobędzie. Zbywanie całej kategorii jako szumu jest błędem.

Na poziomie pojedynczego ustalenia deklarowana krytyczność jest systematycznie zawyżona — w górę, bo jedyne pole, którego nikt nie może sprawdzić, to właśnie to, które wszyscy pompują. Traktowanie każdego alarmu jak wyroku też jest błędem — w drugą stronę.

Błąd polega na odpowiadaniu na pytanie jednego alarmem drugiego. „Gdzieś w tym ekosystemie jest mnóstwo prawdziwych błędów" nie czyni tego ustalenia w waszym wierszu możliwym do wykorzystania. A „większość tych konkretnych alarmów to szum" nie znaczy, że wasza baza kodu jest czysta.

Co widzi na wylot

Średniowieczny edytor nie mógł odkazić całej tradycji. Mógł za to przypiąć warunki do każdej lekcji i uczynić je jawnymi. Ten sam ruch działa tutaj. Gdy ktoś wam podaje ustalenie, pytajcie:

  1. Jaki szczebel dowodowy faktycznie osiąga? Prześledzone w źródle, skompilowane, przetestowane albo odtworzone w działaniu — to nie są te same twierdzenia. Ustalenie nigdy nie powinno nosić pewności wyższej niż praca, która za nim stoi.
  2. Jest osiągalne w waszym buildzie, czy osiągalne w zasadzie? Waga bez argumentu o osiągalności to nastrój, nie pomiar.
  3. Zostało osądzone, czy uśrednione? Zgodność trzech narzędzi to nie trzy potwierdzenia, jeśli narzędzia dzielą martwe pole. Ustalenie mniejszościowe warte jest taniego sprawdzenia wyrocznią — uruchomić test, przeczytać specyfikację, przejść ścieżkę — a nie głosowania.
  4. Jest już naprawione albo już znane? Ustalenie, które opiekunowie zamknęli w zeszłym miesiącu, jest świadkiem historii, nie waszego ryzyka.

Nic z tego nie jest egzotyczne. To właśnie robi edycja krytyczna ze stertą rękopisów: kolacjonuje świadków, osądza ich względem dowodu mocniejszego niż kolejna opinia i zachowuje aparat — osądy, niepewność, lekcje rozważone i odrzucone.

Nie każde martwe ustalenie umarło tą samą śmiercią

Większość ustaleń nie przeżywa. To normalne i o to chodzi — ale to, jak ustalenie umarło, jest informacją, a przegląd, który wszystkie wsypuje do jednego kubła z napisem „odrzucone", tę informację wyrzucił.

Filologia rozdziela przypadki, a rozróżnienie jest na tyle stare, że ma nazwę. Rękopis, o którym wykazano, że został skopiowany z innego zachowanego rękopisu, skreśla się z rachuby w całości — eliminatio codicum descriptorum — nie dlatego, że jest błędny, lecz dlatego, że nie wnosi żadnego niezależnego świadectwa. Jego zgodność nigdy nie była dowodem.

Trzy śmierci — i nie znaczą tego samego:

  • Redundantne. Kilka narzędzi wydało to samo ustalenie. Tam, gdzie te narzędzia nie są niezależne — a dzieląc dane treningowe i szablony, często nie są — ich zgodność to jedna lekcja w trzech odpisach, nie trzy potwierdzenia, a liczenie jej trzykrotnie to sposób, w jaki fabrykuje się fałszywą pewność. Skreślcie duplikaty, ale odnotujcie założenie o niezależności, zamiast je przemilczeć: zgodność naprawdę niezależnych recenzentów nie jest niczym.
  • Fałszywe. Ustalenie mówi, że kod robi coś, czego kod nie robi. Rozstrzyga się otwarciem pliku. To jedyna kategoria, jaką większość ma na myśli, mówiąc „fałszywy alarm".
  • Prawdziwe, lecz o tekście, którego już nie ma. Ustalenie jest trafne — o rewizji od tamtej pory naprawionej. Świadek jest uczciwy; kod się spod niego wysunął. Defekt zamknięty przy przypiętej rewizji upstream nie jest dla tej rewizji fałszywym alarmem i nie powinien być tak księgowany. To jednak obowiązuje tylko wtedy, gdy ustalenie mówi, którą rewizję czytało: raport, który nie umie nazwać swojej rewizji, nie jest uczciwym świadkiem minionego tekstu — jest przeterminowanym twierdzeniem o obecnym.

Tylko drugie jest błędem samej lekcji; nieprzypięty przypadek trzeciego to błąd łańcucha, który go zaraportował. Akta mówiące, jaką śmiercią umarło każde ustalenie, może skontrolować ktoś, kogo tam nie było. Stosunek — „striażowaliśmy dwieście ustaleń do sześciu" — nie może, i nie jest też sygnałem jakości: leniwy łańcuch osiąga ten stosunek, generując śmieci i je wyrzucając. Eliminacja nie jest produktem. Produktem są dowody za tymi, którzy przeżyli.

Po co jest edycja

Powód, by budować edycję zamiast listy: ktoś musi dojść do wyroku, i nie będzie to recenzent.

Opiekun projektu decyduje, czy łatać. Producent decyduje, co trafia do akt technicznych. Zespół bezpieczeństwa klienta korporacyjnego decyduje, czy podpisać. Każde z nich dochodzi do wyroku i każde zostanie później poproszone — przez kogoś mniej życzliwego, z większą ilością czasu — o pokazanie, jak do niego doszło. Tym, czego potrzebują od recenzenta, nie jest kolejna opinia do zważenia. Są to dowody ułożone tak, by ich własna decyzja przetrwała to odpytywanie.

W Europie staje się to wymogiem prawnym, a nie dobrą praktyką. Cyber Resilience Act wymaga od producentów „przeprowadzania skutecznych i regularnych testów i przeglądów bezpieczeństwa produktu z elementami cyfrowymi" (załącznik I część II pkt 3), a dokumentacja techniczna musi zawierać „sprawozdania z prób przeprowadzonych w celu weryfikacji zgodności …" (załącznik VII pkt 6) — przechowywane co najmniej 10 lat po wprowadzeniu do obrotu lub przez okres wsparcia, jeżeli jest dłuższy (art. 13 ust. 13). Zgłaszanie aktywnie wykorzystywanych podatności i poważnych incydentów na mocy art. 14 zaczyna się 11 września 2026 r.; rozporządzenie stosuje się w pełni od 11 grudnia 2027 r.

Przeczytajcie, o co naprawdę chodzi. Nie o czysty skan i nie o niską liczbę. O sprawozdanie z przeprowadzonych prób, przechowywane dekadę, czytelne dla kogoś, kogo nie było w pokoju. Lista ustaleń w pewnych siebie wagach, bez aparatu pod spodem i bez zapisu, co odrzucono i dlaczego, tej lektury nie przetrwa. Edycja — tak. Bo każde twierdzenie nazywa dowody za sobą, każda wyeliminowana lekcja jest odnotowana z powodem, a każda korekta następuje na piśmie.

Obowiązki ciążą na producencie, nie na zewnętrznym recenzencie. Zewnętrzny przegląd opisanego tu rodzaju wspiera dokumentację techniczną, którą składacie; nie jest kompletnymi aktami i nie zastępuje oceny zgodności jednostki notyfikowanej tam, gdzie rozporządzenie jej wymaga. Ale jest tą częścią akt, którą najtrudniej wytworzyć o własnej pracy — bo jedyną właściwością, jaką musi nieść, jest to, że napisał ją ktoś inny niż wy.

Dlaczego nas to obchodzi

W CounterProof praktykujemy adwersaryjny przegląd kodu pisanego przez maszyny, a te pytania nie są dla nas teorią — są naszymi regułami operacyjnymi. Ustalenia są osądzane, nie uśredniane; każde twierdzenie nazywa szczebel dowodowy, który osiągnęło, i ani jednego wyżej; ustalenie naprawione już upstream jest wycofywane, nie liczone; a gdy któreś z naszych własnych twierdzeń nie przeżywa, odwołujemy je na piśmie, publicznie (po angielsku). Nie sprzedajemy liczby ustaleń i odradzalibyśmy kupowanie na jej podstawie. Skanery to kopiści, a skryptorium pracuje już dzień i noc za grosze. Rzadkim dobrem nigdy nie była kopia. Jest nim edycja.

Dłuższy wywód — łącznie z warunkową formą każdego twierdzenia powyżej i granicami naszej własnej metody — znajduje się w naszym dokumencie roboczym o kolacjonowaniu i proweniencji tekstu generowanego przez maszyny, czytelnym w całości tutaj (po angielsku). To szkic preprintu, bez recenzji naukowej, i mówi to wprost.


Liczby powyżej mają źródła: kampania na 501 projektach jest udokumentowana w naszej wcześniejszej notatce; stosunki benchmarku trzech systemów pochodzą z opublikowanego wpisu dostawcy; wskaźnik potwierdzeń curl, zgłoszenie widmowej funkcji i zamknięcie programu bounty relacjonują The New Stack, BleepingComputer i The Register. Cytaty z Cyber Resilience Act odsyłają do rozporządzenia (UE) 2024/2847 w oficjalnej polskiej wersji językowej — te same przepisy, które nosimy na stronie głównej. Tam, gdzie twierdzenie jest naszym wnioskiem, a nie cytowanym ustaleniem — że waga inflacjonuje w górę, że płynność i ważność są niezależne — powiedzieliśmy to. Ta strona jest tłumaczeniem angielskiego oryginału; w razie rozbieżności rozstrzyga oryginał. Jeśli coś tu jest błędne, poprawimy to na piśmie na tej stronie.

← Wszystkie notatki