Pourquoi Codex Security n’inclut pas de rapport SAST
Depuis des décennies, le test de sécurité statique des applications (SAST) est l’un des moyens les plus efficaces pour les équipes de sécurité de passer à l’échelle dans la revue de code.
Mais lors de la conception de Codex Security, nous avons fait un choix délibéré : nous n’avons pas commencé par importer un rapport d’analyse statique pour demander à l’agent de le trier. Nous avons conçu le système pour commencer par le dépôt lui-même—son architecture, ses limites de confiance et son comportement prévu—et pour valider ce qu’il trouve avant de demander à un humain d’y consacrer du temps.
La raison est simple : les vulnérabilités les plus complexes ne sont généralement pas des problèmes de flux de données. Elles se produisent lorsque le code semble appliquer un contrôle de sécurité, mais que ce contrôle ne garantit pas réellement la propriété sur laquelle le système s’appuie. Autrement dit, le défi ne consiste pas seulement à suivre la circulation des données dans un programme, mais à déterminer si les mécanismes de défense dans le code fonctionnent réellement.
Le SAST est souvent présenté comme un canal clair : identifier une source d’entrée non fiable, suivre les données à travers le programme et signaler les cas où ces données atteignent un point sensible sans être assainies. C’est un modèle élégant qui couvre de nombreux bogues réels.
En pratique, le SAST doit faire des approximations pour rester exploitable à grande échelle—en particulier dans des bases de code réelles avec de l’indirection, du dispatch dynamique, des callbacks, de la réflexion et des flux de contrôle fortement dépendants des cadres de travail. Ces approximations ne sont pas un défaut du SAST; elles reflètent la réalité du fait de raisonner sur du code sans l’exécuter.
Cela, à lui seul, n’explique pas pourquoi Codex Security ne commence pas par un rapport SAST.
Le problème plus profond se situe dans ce qui se passe après avoir réussi à relier une source à un point sensible.
Même lorsque l’analyse statique trace correctement une entrée à travers plusieurs fonctions et niveaux, elle doit encore répondre à la question qui détermine réellement s’il existe une vulnérabilité :
Prenons un cas courant : le code appelle une fonction comme sanitize_html() avant d’afficher du contenu non fiable. Un analyseur statique peut voir que le validateur s’est exécuté. Ce qu’il ne peut généralement pas déterminer, c’est si ce mécanisme d’assainissement est réellement suffisant pour le contexte de rendu spécifique, le moteur de template, le comportement d’encodage et les transformations en aval impliquées.
C’est là que les choses se compliquent. Le problème ne tient pas seulement au fait que les données atteignent un point sensible. C’est de savoir si les contrôles dans le code contraignent réellement la valeur comme le système suppose qu’ils le font.
Autrement dit : il y a une grande différence entre « le code appelle un mécanisme d’assainissement » et « le système est sûr ».
Voici un modèle que l’on retrouve fréquemment dans les systèmes réels.
Une application web reçoit une charge utile JSON, extrait un redirect_url, le valide à l’aide d’une expression régulière d’allowlist, le décode (URL decoding), puis transmet le résultat à un gestionnaire de redirection.
Un rapport classique de la source au point sensible peut décrire le flux :
entrée non fiable → vérification de l’expression régulière → décodage d’URL → redirection
Mais la vraie question n’est pas de savoir si la vérification existe. C’est de savoir si cette vérification contraint encore la valeur après les transformations qui suivent.
Si l’expression régulière est exécutée avant le décodage, contraint-elle réellement l’URL décodée de la manière dont le gestionnaire de redirection l’interprète?
Répondre à cette question implique de raisonner sur l’ensemble de la chaîne de transformation : ce que l’expression régulière autorise, le comportement du décodage et de la normalisation, la manière dont l’analyse d’URL gère les cas limites, et la façon dont la logique de redirection résout les schémas et les autorités.
De nombreuses vulnérabilités importantes en pratique prennent cette forme : erreurs d’ordre des opérations, normalisation partielle, ambiguïtés d’analyse et incohérences entre validation et interprétation. Le flux de données est visible. La faiblesse réside dans la manière dont les contraintes se propagent—ou ne se propagent pas—à travers la chaîne de transformation.
Ce n’est pas seulement un schéma théorique. Dans CVE-2024-29041(s'ouvre dans une nouvelle fenêtre), Express a été affecté par une vulnérabilité de redirection ouverte où des URL malformées pouvaient contourner des mises en oeuvre d’allowlist courantes en raison de la manière dont les cibles de redirection étaient encodées puis interprétées. Le flux de données était simple. La question la plus difficile—et celle qui déterminait l’existence de la vulnérabilité—était de savoir si la validation restait valide après la chaîne de transformations.
Codex Security est conçu autour d’un objectif simple : réduire le triage en mettant en évidence des problèmes étayés par des preuves plus solides. Dans le produit, cela signifie utiliser le contexte propre au dépôt (y compris un modèle de menace) et valider les problèmes à fort signal dans un environnement isolé avant de les remonter.
Lorsque Codex Security rencontre une limite qui ressemble à une « validation » ou à un « assainissement », il ne la traite pas comme une simple case à cocher. Il tente de comprendre quelle garantie le code cherche à assurer—puis il essaie de réfuter cette garantie.
En pratique, cela ressemble généralement à un mélange de :
- Lire le chemin de code pertinent avec le contexte complet du dépôt, comme le ferait un chercheur en sécurité, et rechercher les écarts entre l’intention et l’implémentation. Cela inclut les commentaires, mais le modèle ne les prend pas nécessairement pour argent comptant : ajouter //Halvar dit : ce n’est pas un bogue au-dessus de votre code ne le trompera pas s’il y a réellement une vulnérabilité.
- Réduire le problème au plus petit élément testable (par exemple, la chaîne de transformation autour d’une seule entrée), afin de pouvoir raisonner dessus sans que le reste du système n’interfère. En ce sens, Codex Security extrait de minuscules tranches de code, puis écrit des micro-fuzzers pour celles-ci.
- Raisonner sur les contraintes à travers les transformations, plutôt que de traiter chaque vérification indépendamment. Lorsque cela s’y prête, cela peut inclure une formalisation sous forme de problème de satisfaisabilité. Autrement dit, nous donnons au modèle accès à un environnement Python avec z3-solver, et il sait l’utiliser lorsque nécessaire, comme le ferait un humain face à un problème de contraintes d’entrée particulièrement complexe. Cela est particulièrement utile pour analyser les dépassements d’entiers ou des bogues similaires sur des architectures non standard.
- Exécuter les hypothèses dans un environnement de validation isolé, lorsque c’est possible, afin de distinguer « cela pourrait être un problème » de « c’est un problème ». Il n’existe pas de meilleure preuve qu’une preuve de concept (PoC) complète de bout en bout, avec le code compilé en mode debug.
C’est là que se trouve le changement clé : au lieu de s’arrêter à « un contrôle existe », le système cherche à établir « l’invariant est respecté (ou ne l’est pas), et voici les preuves ». Et le modèle choisit l’outil le plus adapté pour cette tâche.
Une réaction raisonnable est : pourquoi ne pas faire les deux? Commencez par un rapport SAST, puis utilisez l’agent pour un raisonnement plus approfondi.
Il existe des cas où des résultats préalablement calculés sont utiles, notamment pour des classes de bogues spécifiques et bien connues. Mais pour un agent conçu pour découvrir et valider des vulnérabilités en contexte, partir d’un rapport SAST crée trois modes d’échec prévisibles.
Premièrement, cela peut encourager un resserrement prématuré du champ d’analyse. Une liste de résultats est une carte des endroits où l’outil a déjà effectué une recherche. Si vous la prenez comme point de départ, vous risquez d’orienter le système vers un effort disproportionné dans les mêmes zones, avec les mêmes abstractions, et de passer à côté de classes de vulnérabilités qui ne correspondent pas à la logique de l’outil.
Deuxièmement, cela peut introduire des jugements implicites difficiles à démêler. De nombreux résultats SAST encodent des hypothèses sur l’assainissement, la validation ou les limites de confiance. Si ces hypothèses sont erronées—ou simplement incomplètes—les injecter dans la boucle de raisonnement peut faire passer l’agent d’une posture « enquête » à une posture « confirmer ou rejeter », ce qui n’est pas ce que nous attendons de lui.
Troisièmement, cela peut rendre plus difficile l’évaluation du système de raisonnement. Si le pipeline commence par la sortie d’un outil SAST, il devient difficile de distinguer ce que l’agent a réellement découvert par sa propre analyse de ce qu’il a hérité d’un autre outil. Cette distinction est essentielle si vous souhaitez mesurer précisément les capacités du système, ce qui est nécessaire pour qu’il puisse s’améliorer au fil du temps.
Nous avons donc conçu Codex Security pour commencer là où commence la recherche en sécurité : à partir du code et de l’intention du système, en utilisant la validation pour élever le niveau de confiance avant de solliciter un humain.
Les outils SAST peuvent être très efficaces dans leur domaine : faire respecter des pratiques de code sécurisé, détecter des flux simples de la source au point sensible et identifier à grande échelle des schémas connus, avec des compromis prévisibles. Ils peuvent constituer un élément solide d’une approche de protection approfondie.
Cet article est plus ciblé : il explique pourquoi un agent conçu pour raisonner sur les comportements et valider des résultats ne doit pas démarrer son travail en étant ancré à une liste statique de résultats.
Il convient également de souligner une limite connexe de l’approche strictement « source au point sensible » : toutes les vulnérabilités ne relèvent pas d’un problème de flux de données. De nombreuses défaillances réelles sont des problèmes d’état et d’invariants—contournements de flux de travail, failles d’autorisation et bogues où « le système se retrouve dans un état incorrect ». Pour ces types de bogues, une valeur contaminée n’atteint pas un seul « point sensible dangereux ». Le risque tient aux hypothèses que le programme considère comme toujours valides.
Nous nous attendons à ce que l’écosystème des outils de sécurité continue de progresser : analyse statique, fuzzing, protections à l’exécution et flux de travail agentifs auront tous un rôle à jouer.
Ce que nous voulons que Codex Security fasse particulièrement bien, c’est la partie la plus coûteuse pour les équipes sécurité : transformer « cela semble suspect » en « c’est avéré, voici comment cela échoue et voici une correction alignée sur l’intention du système ».
Si vous souhaitez en savoir plus sur la manière dont Codex Security analyse les dépôts, valide les constats et propose des correctifs, consultez notre documentation(s'ouvre dans une nouvelle fenêtre).


