CounterProof

Een bevinding is geen vonnis

AI kan inmiddels in een middag duizenden bevindingen over kwetsbaarheden genereren. Een bevinding is een getuige, geen vonnis, en het ene veld dat niemand kan controleren, is het veld dat iedereen opblaast. Zo leest u de stortvloed zonder erin te verdrinken.

In ongeveer 108 uur verstreken campagnetijd in augustus 2026 liet één vrijwilligersinitiatief een model met open gewichten over 501 opensourceprojecten rond Bitcoin lopen en registreerde 7.958 potentiële beveiligingsbevindingen, waarvan 1.280 gemarkeerd als hoog of kritiek. Over die campagne, en de regelgeving waarmee ze botst, schreven we in The Machines Are Reading the Code. Deze notitie gaat over het getal zelf.

Een beveiligingsleverancier heeft namelijk een benchmark gepubliceerd waarin drie AI-systemen voor code review het opnemen tegen een niet-openbare testapplicatie: het ene vond 68 van de 89 bewust ingebrachte kwetsbaarheden, een tweede 60, een derde 58. De leveranciers concurreren nu op die verhouding: meer bevindingen, tegen lagere kosten. Vinden is handelswaar geworden in een prijzenoorlog.

Het loont dus om duidelijk te zeggen wat een bevinding eigenlijk is, want de telling meet het verkeerde.

Een bevinding is een getuige, geen vonnis

Tekstwetenschappers hebben dit vijf eeuwen geleden uitgemaakt, en het woord dat zij ervoor gebruiken, is exact.

Wanneer een antieke tekst in veel met de hand gekopieerde handschriften bewaard is gebleven, is geen enkele kopie de tekst. Elke kopie is een getuige: een afgeleid document dat het origineel bevat, plus de verschrijvingen, gewoonten en overgeërfde afwijkingen van de kopiist. Als drie handschriften overeenstemmen, kan dat betekenen dat de lezing echt is, of dat alle drie afstammen van dezelfde gebrekkige legger. De discipline die dit uitzoekt, levert een kritische editie op: de tekst zoals die het best kan worden vastgesteld, met daaronder een apparaat dat elke gewogen getuige vastlegt, elke variant, elk editorisch oordeel en de gronden ervoor.

Een door AI gegenereerde bevinding over een kwetsbaarheid is in precies deze zin een getuige. Ze is niet het defect. Ze is het rapport van één model over een defect: de werkelijke eigenschappen van de code, vermengd met de gewoonten van het model, de afstamming van zijn training en de prompt waaruit het rapport voortkwam. Als twee scanners het eens zijn, kan dat betekenen dat de bug echt is, of dat beide dezelfde blinde vlekken en dezelfde sjablonen delen. Omdat ze grotendeels op hetzelfde openbare corpus zijn getraind, is dat vaak zo. Overeenstemming tussen gecorreleerde getuigen is bewijs over de getuigen, niet over de code.

En de zwaarst bevochten regel van de tekstwetenschappers is hier onverkort van toepassing. De vloeiende lezing is de verdachte: kopiisten strijken een moeilijke passage glad tot een gemakkelijk cliché, en de gladde versie is vaker de verbetering van de kopiist dan de woorden van de auteur. Een kwetsbaarheidsrapport heeft een vast genre: titel, zwakheidsklasse, ernst, een verwijzing, een alinea “een aanvaller zou…”. Een taalmodel produceert die vorm overtuigend, of het defect nu bestaat of niet. De glans bevat geen informatie over de waarheid. In dit genre is vloeiendheid geen keurmerk. Het is wat er gecontroleerd moet worden.

Daarom is de telling de verkeerde eenheid. Ze telt getuigen en rapporteert ze als vonnissen.

Bij de ernst overdrijven de rapporten

De inflatie is niet gelijkmatig. Ze concentreert zich op één punt, om een structurele reden die het benoemen waard is.

“Deze functie vergelijkt een tijdstempel in milliseconden met een kolom met een precisie van seconden” is een bewering die naar iets verwijst: een bestand, een regel, een commit. U kunt het openen en de kwestie in een minuut beslechten. “Critical” verwijst nergens naar. Er is geen regel code waarin Critical staat. Ernst is een oordeel over bereikbaarheid, uitbuitbaarheid en de reikwijdte van de impact, en omdat dat oordeel geen anker in de broncode heeft, is het precies de plek waar een vloeiende generator ongecontroleerd naar boven afdrijft. De dramatische lezing is de gemakkelijkere; elke prikkel in de rapportageketen beloont een hoger getal; en niets in het artefact biedt weerstand.

Dus wanneer een campagne 1.280 bevindingen als “hoog of kritiek” rapporteert, luidt de eerlijke lezing: 1.280 bevindingen die een generator als hoog of kritiek heeft gelabeld. Het label is het minst controleerbare veld in het document, en het doet het meeste werk in de kop.

Zijn ze uitbuitbaar? Dat heeft nog niemand gezegd

Tussen een bevinding en een defect zit een stap die de telling overslaat, de toetsing: beslissen welke bevindingen echt zijn, welke bereikbaar zijn en welke ertoe doen. Die stap is nog altijd mensenwerk, en hij schaalt niet mee met het genereren.

De duidelijkste openbare meting van wat er gebeurt als die stap wordt overgeslagen, komt van curl. Het securityteam van curl, dat uit zeven vrijwilligers bestaat, zag het aandeel bevestigde kwetsbaarheidsmeldingen dalen van boven de 15 procent naar onder de 5 procent toen er inzendingen met hulp van AI binnenkwamen, waarbij elke ongegronde melding nog steeds uren kostte om te weerleggen. Eén ervan kwam compleet met GDB-sessies en registerdumps voor een HTTP/3-exploit in een functie die in curl niet bestaat. De maintainer van curl beschreef de triagelast als “gelijkstaand aan een DDoS”, en uiteindelijk sloot het project zijn bugbountyprogramma, met de mededeling dat het geen enkele geldige beveiligingsmelding had gezien die met hulp van AI tot stand was gekomen.

Lees dat getal op de juiste manier. Het bewijst niet dat AI-bevindingen waardeloos zijn; het bewijst dat de vloeiendheid van een bevinding en haar geldigheid onafhankelijk van elkaar zijn, en dat de signaal-ruisverhouding instort zodra de toetsingsstap wordt weggehaald. De meldingen werden talrijker en zelfverzekerder; het aandeel dat de controle doorstond, ging omlaag.

De stortvloed is een beveiligingsprobleem, geen overlast

Het is verleidelijk om “te veel bevindingen” af te doen als een ergernis. Dat is het niet. Wanneer het genereren sneller gaat dan de toetsing, verdwijnt de echte bevinding niet (ze raakt begraven in de wachtrij achter tweehonderd aannemelijke, en een wachtrij die niemand kan wegwerken, is een wachtrij die dingen verbergt). Het woord dat curl ervoor gebruikt, DDoS, is geen overdrijving. Een team dat verdrinkt in zelfverzekerde meldingen, is niet veiliger dan een team zonder meldingen; het is een team waarvan de aandacht is uitgeput door getuigen die nooit aan een kruisverhoor zijn onderworpen.

Houd de twee alarmen uit elkaar

Hier worden twee beweringen door elkaar gehaald, en die scheiden is de hele discipline.

Alles bij elkaar is het gevaar reëel. Er zitten werkelijk enorme aantallen niet-verholpen defecten in oude code, en een goedkope, onvermoeibare vinder zal er een deel van aan het licht brengen. De hele categorie afdoen als hype is onjuist.

Per bevinding wordt de opgegeven ernst stelselmatig overdreven: naar boven, omdat het ene veld dat niemand kan controleren, het veld is dat iedereen opblaast. Elke melding als vonnis behandelen is ook onjuist, in de tegenovergestelde richting.

De fout is een van beide alarmen te gebruiken om de vraag van het andere te beantwoorden. “Ergens in dit ecosysteem bestaan veel echte bugs” maakt deze bevinding op uw regel niet uitbuitbaar. En “de meeste van deze specifieke meldingen zijn ruis” betekent niet dat uw codebase schoon is.

Wat erdoorheen kijkt

De middeleeuwse editor kon de hele overlevering niet van contaminatie zuiveren. Wat de editor wel kon, was aan elke lezing voorwaarden verbinden en die voorwaarden expliciet maken. Dezelfde zet werkt hier. Wanneer u een bevinding krijgt aangereikt, vraag dan:

  1. Welk bewijsniveau bereikt ze werkelijk? Broncodetrace, compileerbewijs, test of live reproductie: dat zijn niet dezelfde beweringen. Een bevinding hoort nooit een grotere zekerheid uit te stralen dan het werk erachter.
  2. Is ze bereikbaar in uw build, of in principe bereikbaar? Ernst zonder argument over bereikbaarheid is een stemming, geen meting.
  3. Is ze getoetst, of uitgemiddeld? Drie tools die het eens zijn, vormen geen drie bevestigingen als de tools een blinde vlek delen. Een minderheidsbevinding verdient een goedkope orakelcontrole (de test draaien, de specificatie lezen, het pad uitvoeren), geen stemronde.
  4. Is ze al verholpen, of al bekend? Een bevinding die de maintainers vorige maand hebben gesloten, is een getuige van de geschiedenis, niet van uw risico.

Niets daarvan is exotisch. Het is wat een kritische editie met een stapel handschriften doet: de getuigen collationeren, toetsen aan bewijs dat sterker is dan nog een mening, en het apparaat bewaren: de oordelen, de onzekerheid, de lezingen die zijn overwogen en verworpen.

Niet elke dode bevinding is op dezelfde manier gestorven

De meeste bevindingen overleven het niet. Dat is normaal, en het is de bedoeling, maar hoe een bevinding is gestorven, is informatie, en een review die ze allemaal in één bak met het opschrift “afgewezen” kiepert, heeft die informatie weggegooid.

Tekstwetenschappers houden de gevallen uit elkaar, en het onderscheid is oud genoeg om een naam te hebben. Een handschrift waarvan is aangetoond dat het is overgeschreven van een ander, nog bestaand handschrift, wordt volledig uit de afweging geschrapt (eliminatio codicum descriptorum), niet omdat het fout is, maar omdat het geen onafhankelijke getuigenis toevoegt. Zijn overeenstemming was van meet af aan geen bewijs.

Drie manieren van sterven, en ze betekenen niet hetzelfde:

  • Overbodig. Meerdere tools leverden dezelfde bevinding op. Waar die tools niet onafhankelijk zijn (en omdat ze trainingsdata en sjablonen delen, zijn ze dat vaak niet), is hun overeenstemming één lezing in drie kopieën in plaats van drie bevestigingen, en haar driemaal tellen is de manier waarop vals vertrouwen wordt gefabriceerd. Schrap de duplicaten, maar leg de aanname over onafhankelijkheid vast in plaats van haar weg te redeneren: overeenstemming tussen werkelijk onafhankelijke reviewers is niet niets.
  • Onwaar. De bevinding zegt dat de code iets doet wat de code niet doet. Beslecht door het bestand te openen. Dit is de enige categorie die de meeste mensen voor ogen hebben als ze “false positive” zeggen.
  • Waar, maar over een tekst die niet meer bestaat. De bevinding klopt: over een revisie die sindsdien is hersteld. De getuige is eerlijk; de code is eronder verschoven. Een defect dat is gesloten bij een vastgelegde upstream-revisie, is voor die revisie geen false positive en hoort niet als zodanig te worden geregistreerd. Dat geldt alleen als de bevinding zegt welke revisie ze heeft gelezen: een rapport dat zijn revisie niet kan noemen, is geen eerlijke getuige van een achterhaalde tekst, maar een verouderde bewering over de huidige.

Alleen de tweede is een fout in de lezing zelf; het geval binnen de derde waarin geen revisie is vastgelegd, is een fout in de pipeline die de bevinding rapporteerde. Een dossier dat vermeldt welke dood elke bevinding is gestorven, kan worden gecontroleerd door iemand die er niet bij was. Een verhouding (“we hebben tweehonderd bevindingen via triage teruggebracht tot zes”) kan dat niet, en is evenmin een kwaliteitssignaal: een luie pipeline bereikt die verhouding door rommel te genereren en weg te gooien. De eliminatie is niet het product. Het bewijs achter de overlevenden is dat wel.

Waarvoor een editie dient

De reden om een editie te maken in plaats van een lijst, is dat iemand tot een vonnis moet komen, en dat zal niet de reviewer zijn.

Een maintainer beslist of er wordt gepatcht. Een fabrikant beslist wat er in de technische documentatie komt. Het securityteam van een zakelijke klant beslist of er wordt getekend. Ieder van hen komt tot een vonnis, en ieder van hen zal later (door iemand die minder vriendelijk is en meer tijd heeft) worden gevraagd te laten zien hoe dat vonnis tot stand kwam. Wat zij van een reviewer nodig hebben, is niet nog een mening om af te wegen. Het is het bewijs, zo geordend dat hun eigen beslissing standhoudt wanneer die vraag wordt gesteld.

In Europa wordt dit een wettelijke eis in plaats van goede praktijk. De Cyber Resilience Act (officieel: de Verordening cyberweerbaarheid) schrijft voor dat fabrikanten “de beveiliging van het product met digitale elementen op doeltreffende en regelmatige wijze testen en evalueren” (bijlage I, deel II, punt 3), en de technische documentatie moet “verslagen van de tests die zijn uitgevoerd om de conformiteit van het product met digitale elementen en van de procedures inzake de respons op kwetsbaarheden … te verifiëren” bevatten (bijlage VII, punt 6); die documentatie moet ten minste tien jaar nadat het product in de handel is gebracht, of gedurende de ondersteuningsperiode als die langer is, ter beschikking van de markttoezichtautoriteiten worden gehouden (artikel 13, lid 13). De meldingsplicht van artikel 14 voor actief uitgebuite kwetsbaarheden en ernstige incidenten begint op 11 september 2026; de verordening is volledig van toepassing vanaf 11 december 2027.

Lees wat daar werkelijk wordt gevraagd. Geen schone scan, en geen laag getal. Een verslag van uitgevoerde tests, tien jaar bewaard, leesbaar voor iemand die er niet bij was. Een lijst bevindingen met zelfverzekerde ernstniveaus, zonder apparaat eronder en zonder vastlegging van wat is verworpen of waarom, doorstaat die lezing niet. Een editie wel: omdat elke bewering het bewijs erachter vermeldt, elke geëlimineerde lezing met haar reden is vastgelegd, en elke correctie op schrift staat.

De verplichtingen liggen bij de fabrikant, niet bij een externe reviewer. Een externe review van het hier beschreven soort ondersteunt de technische documentatie die u samenstelt; ze is niet het volledige dossier, en ze is geen vervanging voor een conformiteitsbeoordeling door een aangemelde instantie waar de verordening die voorschrijft. Maar ze is het deel van dat dossier dat over uw eigen werk het moeilijkst te maken is, omdat de ene eigenschap die ze moet dragen, is dat iemand anders dan u haar heeft geschreven.

Waarom het ons aangaat

Bij CounterProof doen we adversariële review van door machines geschreven code, en deze vragen zijn voor ons niet theoretisch; het zijn onze werkregels. Bevindingen worden getoetst, niet uitgemiddeld; elke bewering noemt het bewijsniveau dat ze heeft bereikt, en geen hoger; een bevinding die upstream al is verholpen, wordt ingetrokken in plaats van meegeteld; en wanneer een van onze eigen beweringen de toets niet doorstaat, trekken we die schriftelijk en openbaar in. We verkopen geen aantal bevindingen, en we zouden u afraden op basis van zo’n aantal te kopen. De beweringen die we weigeren namens een klant te doen, staan op What we will not claim. De scanners zijn kopiisten, en het scriptorium draait nu dag en nacht voor een paar cent. Het schaarse goed was nooit de kopie. Het is de editie.

Het uitgebreidere argument (inclusief de voorwaardelijke vorm van elke bewering hierboven, en de grenzen van onze eigen methode) staat in ons werkdocument over collatie en herkomst bij door machines gegenereerde tekst, hier volledig te lezen. Het is een preprint in conceptvorm, niet peer-reviewed, en dat staat er ook in.


De cijfers hierboven zijn onderbouwd: de campagne over 501 projecten is gedocumenteerd in onze eerdere notitie; de verhoudingen uit de benchmark van drie systemen komen uit het gepubliceerde bericht van de leverancier; het percentage bevestigde meldingen bij curl, de melding over de spookfunctie en de sluiting van het bountyprogramma zijn beschreven door The New Stack, BleepingComputer en The Register. Verwijzingen naar de Cyber Resilience Act betreffen Verordening (EU) 2024/2847 en zijn dezelfde als op onze homepage; de citaten zijn gecontroleerd aan de hand van de officiële Nederlandse taalversie van die verordening. Waar een bewering onze eigen gevolgtrekking is in plaats van een geciteerde bevinding (dat de ernst naar boven wordt opgeblazen, dat vloeiendheid en geldigheid onafhankelijk zijn), hebben we dat gezegd. Deze pagina is een vertaling van het Engelse origineel; bij verschillen geldt het origineel. Als we hier iets verkeerd hebben, corrigeren we dat schriftelijk op deze pagina.

← Alle notities