Waarom Codex Security geen SAST-rapport bevat
Al tientallen jaren is static application security testing (SAST) een van de meest effectieve manieren waarop beveiligingsteams codereviews op schaal uitvoeren.
Toen we Codex Security ontwikkelden, maakten we een bewuste ontwerpkeuze: we begonnen niet met het importeren van een statisch analyserapport en lieten de agent dat niet eerst beoordelen. We hebben het systeem zo ontworpen dat het begint met de repository zelf, de architectuur ervan, vertrouwensgrenzen en beoogd gedrag, en dat het valideert wat het aantreft voordat het een mens vraagt er tijd aan te besteden.
De reden is simpel: de moeilijkste kwetsbaarheden zijn meestal geen dataflowproblemen. Ze doen zich voor wanneer code lijkt te zorgen voor een beveiligingscontrole, maar die controle garandeert niet werkelijk de eigenschap waar het systeem op vertrouwt. Met andere woorden, de uitdaging is niet alleen om bij te houden hoe gegevens door een programma bewegen, maar het is om te bepalen of de verdedigingsmaatregelen in de code echt werken.
SAST wordt vaak neergezet als een helder proces: je identificeert een bron van onbetrouwbare input, volgt hoe data door het programma stroomt en markeert gevallen waarin die data een gevoelige sink bereikt zonder sanitization. Het is een elegant model, en het dekt veel echte bugs.
In de praktijk moet SAST vereenvoudigingen maken om op schaal werkbaar te blijven, vooral in echte codebases met indirectie, dynamische dispatch, callbacks, reflection en door frameworks aangestuurde control flow. Die vereenvoudigingen zijn geen kritiek op SAST; ze horen bij de realiteit van redeneren over code zonder die uit te voeren.
Dat is op zich niet de reden waarom Codex Security niet met een SAST-rapport begint.
Het diepere probleem is wat er gebeurt nadat je met succes een bron naar een sink hebt getraceerd.
Zelfs wanneer statische analyse invoer correct traceert over meerdere functies en lagen, moet ze nog steeds de vraag beantwoorden die daadwerkelijk bepaalt of er een kwetsbaarheid bestaat:
Neem een gangbaar patroon: code roept iets aan zoals sanitize_html() voordat onbetrouwbare content wordt gerenderd. Een statische analyzer kan zien dat de sanitizer is uitgevoerd. Wat het doorgaans niet kan vaststellen, is of die sanitizer daadwerkelijk volstaat voor de specifieke renderingcontext, template-engine, coderingsgedrag en de betrokken downstream-transformaties.
Daar wordt het lastig. Het probleem is niet alleen of data een sink bereikt. Het gaat erom of de controles in de code de waarde daadwerkelijk beperken op de manier die het systeem veronderstelt.
Anders gezegd: er is een groot verschil tussen "de code roept een sanitizer aan” en “het systeem is veilig.”
Dit is een patroon dat in echte systemen voortdurend voorkomt.
Een webapplicatie ontvangt een JSON-payload, extraheert een redirect_url, valideert deze tegen een allowlist-regex, de URL-decodeert deze en geeft het resultaat door aan een redirect-handler.
Een klassiek source-to-sink-rapport kan de stroom beschrijven:
onbetrouwbare invoer → regexcontrole → URL decoderen → omleiden
Maar de echte vraag is niet of de check bestaat. Het gaat erom of die controle de waarde na de daaropvolgende transformaties nog steeds beperkt.
Als de regex vóór het decoderen wordt uitgevoerd, beperkt die dan daadwerkelijk de gedecodeerde URL op de manier waarop de redirect handler die interpreteert?
Om die vraag te beantwoorden, moet je redeneren over de volledige transformatieketen: wat de regex toelaat, hoe decoding en normalisatie werken, hoe URL-parsing met randgevallen omgaat en hoe de redirectlogica schemes en authorities afhandelt.
Veel van de kwetsbaarheden die er in de praktijk toe doen, zien er zo uit: fouten in de volgorde van bewerkingen, gedeeltelijke normalisatie, parsing-ambiguïteiten en mismatches tussen validatie en interpretatie. De dataflow is zichtbaar. De zwakte zit in hoe beperkingen zich voortplanten, of niet voortplanten, door de transformatieketen.
Dit is niet alleen een theoretisch patroon. In CVE-2024-29041(opent in een nieuw venster) had Express te maken met een open redirect-kwetsbaarheid waarbij ongeldig gevormde URL’s allowlist-implementaties konden omzeilen door de manier waarop redirect-doelen werden geëncodeerd en geïnterpreteerd. De dataflow was eenvoudig. De moeilijkere vraag, en de vraag die bepaalde of de bug bestond, was of de validatie nog steeds standhield na de transformatieketen.
Codex Security is gebouwd rondom een eenvoudig doel: triage verminderen door problemen aan het licht te brengen met sterker bewijs. In het product betekent dat het gebruik van repo-specifieke context (inclusief een threat model) en het valideren van high-signal issues in een afgeschermde omgeving voordat je ze naar voren brengt.
Wanneer Codex Security een boundary tegenkomt die eruitziet als ‘validatie’ of ‘sanitization’, behandelt het dat niet als een formaliteit. Het probeert te begrijpen wat de code probeert te garanderen en vervolgens probeert het die garantie te ontkrachten.
In de praktijk ziet dat er vaak uit als een mix van:
- Het relevante codepad lezen binnen de volledige repository-context, zoals een beveiligingsonderzoeker dat zou doen, en mismatches tussen intentie en implementatie opsporen. Dit omvat commentaar, maar het model gelooft commentaar niet per se, dus //Halvar says: this is not a bug boven je code toevoegen brengt het niet in verwarring als er daadwerkelijk een bug is.
- Het probleem terugbrengen tot het kleinste testbare deel (bijvoorbeeld de transformatiepipeline rond één input), zodat je erover kunt redeneren zonder ruis van de rest van het systeem. In deze zin haalt Codex Security kleine stukjes code eruit en schrijft er vervolgens micro-fuzzers voor.
- Redeneren over beperkingen over meerdere transformaties heen, in plaats van elke controle afzonderlijk te behandelen. Waar passend kan dit worden geformaliseerd als een satisfiability-probleem. Met andere woorden: we geven het model toegang tot een Python-omgeving met z3-solver, en het kan die gebruiken wanneer dat nodig is, net zoals een mens dat zou doen bij het oplossen van een bijzonder complex inputconstraint-probleem. Dit is vooral nuttig bij het analyseren van integer overflow en vergelijkbare bugs op niet-standaardarchitecturen.
- Waar mogelijk hypotheses uitvoeren in een afgeschermde validatieomgeving, om “dit zou een probleem kunnen zijn” te onderscheiden van “dit is een probleem”. Er is geen beter bewijs dan een volledige end-to-end-PoC met de code gecompileerd in debug mode.
Dit is de belangrijkste verschuiving: in plaats van te stoppen bij “er bestaat een controle”, stuurt het systeem aan op “de invariant geldt (of niet), en hier is het bewijs”. En het model kiest de beste tool voor die taak.
Een redelijke reactie is: waarom niet allebei? Begin met een SAST-rapport en gebruik vervolgens de agent om dieper te redeneren.
Er zijn gevallen waarin vooraf berekende bevindingen nuttig zijn, vooral voor smalle, bekende types bugs. Maar voor een agent die is ontworpen om kwetsbaarheden in context te ontdekken en te valideren, leidt beginnen met een SAST-rapport tot drie voorspelbare faalmodi.
Ten eerste kan het voortijdige beperkingen aanmoedigen. Een lijst met bevindingen is een kaart van waar een tool al heeft gekeken. Als je het als uitgangspunt neemt, kan het systeem onevenredig veel nadruk leggen op dezelfde gebieden, met dezelfde abstracties, en problemen missen die niet in het wereldbeeld van de tool passen.
Ten tweede kan het impliciete oordelen introduceren die moeilijk terug te draaien zijn. Veel SAST-bevindingen bevatten aannames over sanitisatie, validatie of vertrouwensgrenzen. Als die aannames onjuist zijn, of gewoon onvolledig, kan het invoeren ervan in de redenering de agent van 'onderzoeken' naar 'bevestigen of verwerpen' verschuiven, wat niet is wat we willen dat de agent doet.
Ten derde kan het ook moeilijker maken om de redenering te evalueren. Als de pijplijn begint met SAST-output, wordt het moeilijk om te scheiden wat de agent via zijn eigen analyse heeft ontdekt van wat hij van een andere tool heeft overgenomen. Die scheiding is belangrijk als je de capaciteiten van het systeem nauwkeurig wilt meten, wat nodig is om het systeem in de loop van de tijd te verbeteren.
Daarom hebben we Codex Security gebouwd om te beginnen waar beveiligingsonderzoek begint: bij de code en de intentie van het systeem, met validatie om de lat voor betrouwbaarheid hoger te leggen voordat we een mens onderbreken.
SAST-tools kunnen uitblinken in waar ze voor zijn ontworpen: het afdwingen van veilige coderingsstandaarden, het opsporen van eenvoudige source-to-sink-problemen en het op schaal detecteren van bekende patronen met voorspelbare trade-offs. Ze kunnen een sterk onderdeel zijn van diepgaande verdediging.
Deze post is beperkter: hij gaat over waarom een agent die is ontworpen om over gedrag te redeneren en bevindingen te valideren, zijn werk niet moet beginnen met een vaste lijst met bevindingen als ankerpunt.
Het is ook de moeite waard om een gerelateerde beperking van puur source-to-sink-denken te benoemen: niet elke kwetsbaarheid is een dataflowprobleem. Veel echte fouten zijn problemen met status en invarianten: workflows die worden omzeild, autorisatielekken en bugs waarbij 'het systeem zich in de verkeerde toestand bevindt'. Voor dit soort bugs bereikt een besmette waarde geen enkele 'gevaarlijke sink'. Het risico zit in wat het programma veronderstelt dat altijd waar zal zijn.
We verwachten dat het ecosysteem voor securitytooling blijft verbeteren: statische analyse, fuzzing, runtime-guards en agentic workflows zullen allemaal een rol spelen.
Waar Codex Security goed in moet zijn, is het deel dat beveiligingsteams het meeste kost: van “dit ziet er verdacht uit” naar “dit is een echte kwetsbaarheid, zo gaat het mis, en hier is een oplossing die aansluit bij hoe het systeem bedoeld is.”
Als je meer wilt weten over hoe Codex Security repository's scant, bevindingen valideert en oplossingen voorstelt, lees dan onze documentatie(opent in een nieuw venster).


