Choisir un SAST sans se faire avoir

Deux outils analysent votre application. Le premier remonte huit alertes, le second seize. Lequel choisir ?
Sans savoir ce qu'ils ont lu, ce qu'ils ont raté et le temps nécessaire pour traiter leurs résultats, ces chiffres ne permettent pas de trancher. Voici comment construire un essai qui vous donne une réponse.

Cet article prolonge Le SAST en profondeur, mais se lit seul.

Partir du travail à faire

Le bon outil doit couvrir votre code et trouver sa place dans votre équipe. Avant une démonstration, écrivez trois contraintes :

  • Le code indispensable. Langages, frameworks, code généré, taille du dépôt et possibilité de compiler. Une case « Java pris en charge » ne dit pas si vos entrées web et vos bibliothèques internes sont comprises.
  • Le moment de la décision. Un contrôle avant fusion et une analyse approfondie de nuit n'ont pas le même budget de temps. Précisez ce qui doit bloquer une livraison et qui peut trancher une alerte contestée.
  • Les conditions d'exploitation. Code autorisé à quitter votre réseau ou non, connexion Internet disponible, droits requis, budget et personne chargée de maintenir les règles.

Un moteur détecte. Une plateforme ajoute notamment la gestion des résultats, les droits et les intégrations. Dans l'offre comparée, distinguez ce qui est inclus, ce qui demande un autre produit et ce que votre équipe devra construire.

Le piège du score à 100

Un banc d'essai public est l'OWASPOWASP : une fondation qui publie des guides et des outils libres de sécurité applicative Benchmark Java 1.2, publié par l'OWASP (Open Worldwide Application Security Project), une fondation à but non lucratif.

2 740

petits programmes de test

1 415

vraies vulnérabilités

1 325

cas sans la faille testée

Les effectifs ci-dessus viennent du fichier des résultats attendus de la version 1.2.

Son score est la part des failles trouvées moins la part des cas sûrs signalés à tort : un outil qui signale tout obtient zéro.
C'est une bonne idée.

Mais ce corpus Java est synthétique (il existe aussi un corpus Python) : un score excellent dit peu de chose du comportement de l'outil sur votre code. Et méfiez-vous de la loi de Goodhart : quand une mesure devient un objectif, elle cesse d'être une bonne mesure. Un réglage optimisé sur ce corpus peut améliorer le score sans améliorer la détection sur votre application.

Même limite pour la suite Juliet du NIST, des dizaines de milliers de cas synthétiques en C, C++ et Java : utile pour tester des règles, insuffisante à elle seule pour choisir un outil.

Les moteurs SAST, en une minute chacun

Avec le vocabulaire de l'article approfondi (arbre syntaxique, taint, sensibilités), ces moteurs se lisent mieux (fiches vérifiées le 8 octobre 2026, sources dans les noms des outils). Ils ne sont pas interchangeables : choisissez d'abord ceux qui couvrent vos langages et vos types de défauts. Pour chacun : ce qu'il construit, ce qu'il cherche, et sa limite.

MoteurCe qu'il construitCe qu'il chercheAngle mort
Opengrep et SemgrepOpengrep : fork libre de Semgrep, LGPL-2.1, depuis janvier 2025.Un arbre syntaxique, l'équivalent de l'analyse grammaticale d'une phrase, dans une représentation commune aux langages pris en charge.Des règles écrites comme le code visé, avec des jokers, plus du taint.La portée dépend du moteur, de l'édition et du langage.
CodeQLRequêtes ouvertes, CLI soumis aux conditions GitHub.Une base de données du code, produite par un extracteur par langage.Des requêtes de sécurité fournies, extensibles avec le langage QL.Préparation de la base ; expertise nécessaire pour les requêtes personnalisées.
JoernLibre, Apache 2.0.Un graphe de propriétés du code : syntaxe, flot de contrôle et dépendances superposés.Des requêtes sur le graphe, interactives ou exécutées par script.L'intégration continue exige une configuration adaptée.
PysaPublié par Meta, licence MIT.Des résumés de fonctions, aidés par le type de chaque valeur (texte, nombre, objet).Des flux de taint calculés par passes successives, jusqu'à stabilité.Python uniquement.
InferPublié par Meta, licence MIT.Une description mathématique de ce que chaque fonction fait de la mémoiremémoire : l'espace où le programme range ses données pendant qu'il tourne.Des défauts de mémoire et de concurrence, selon les analyses activées.Fait pour les pointeurs nulspointeurs nuls : des références vers une donnée qui n'existe pas, qui font planter le programme et les fuites plus que pour les injections web.
SpotBugs et Find Security BugsLibre.Des graphes de contrôle et analyses de flux du Java compilécompilé : traduit en bytecode, le format intermédiaire que la machine virtuelle Java exécute.Des appels dangereux connus dans les frameworksframeworks : des boîtes à outils prêtes à l'emploi pour construire une application web Java les plus courants.Exige un projet compilé.

Pour Checkmarx, Snyk Code et SonarQube, vérifiez l'édition, les langages et les modèles inclus dans l'offre datée du fournisseur.

Juger un SAST sur votre code

Sur une copie de votre dépôt, fixez le périmètre, les versions des outils, les règles, les exclusions et les ressources disponibles. Conservez les commandes et rapports pour pouvoir rejouer l'essai. Comparez d'abord les réglages par défaut, puis notez le temps passé à les adapter.

Préparer un essai que vous pourrez rejouer
  1. Choisir le périmètre. Un dépôt représentatif, ses dépendances et ses commandes de compilation. Garder la même copie pour tous les candidats.
  2. Établir les cas de référence. Quelques vulnérabilités dont vous connaissez la cause, leur version corrigée et du code sain ressemblant à une faille. Inclure votre framework réel. Consigner la réponse attendue avant de lancer les outils.
  3. Faire deux passages. D'abord sans réglage spécifique au corpus, puis avec un même budget de configuration. Garder quelques cas à part pour vérifier que les modèles ne sont pas adaptés seulement aux exemples montrés.
  4. Faire trier par l'équipe. Le développeur et l'AppSec examinent les mêmes alertes, sans la conclusion de l'éditeur sous les yeux. Noter les désaccords, le temps de compréhension et les éléments manquants.
  5. Conserver la preuve. Versions, configuration, fichiers ignorés, erreurs, résultats et décisions. Une alerte disparue après une panne ou une exclusion n'est pas une correction.
  6. Détail des cinq essais du tableau. Flux : vérifier chaque alerte et sa disparition après correction, à configuration identique. Échantillon : 50 alertes, ou toutes si moins, en mesurant séparément les failles connues retrouvées et manquées. Sanitizer : le cas sans protection et celui avec une protection inadaptée doivent encore déclencher. Fichier illisible : vérifier le diagnostic, la couverture partielle ou l'absence d'analyse, et la raison de l'exclusion. Pull request : distinguer première analyse et analyses avec cache, et noter durée totale, mémoire et dépassements de délai.

Cinq questions, la preuve à exiger, et l'essai à faire soi-même :

QuestionPreuve à demanderEssai sur votre dépôt
Jusqu'où va le suivi de données ?Par fonction, par fichier, entre fichiers, pour vos langages et vos frameworks.Un flux vulnérable dans une fonction, puis entre deux fichiers, avant et après correction.
Montrez-moi le chemin.Le chemin des flux, ou le contexte et la justification des autres alertes.Relire un échantillon aléatoire d'alertes et compter les confirmées et les indécises.
Comment déclare-t-on nos sanitizers et nos entrées ?Le format des modèles, avec un exemple sur votre framework.Modéliser une protection vérifiée : le cas protégé doit être écarté, les autres doivent encore déclencher.
Que se passe-t-il quand l'outil ne lit pas un fichier ?La couverture réelle : fichiers analysés, ignorés, et pourquoi.Ajouter un fichier à erreur de syntaxe et un fichier exclu : aucun ne doit passer pour sûr.
Combien de temps sur une pull request ?Le temps d'analyse d'une modification, sur un dépôt de votre taille.Rejouer des modifications représentatives, à ressources fixes, avec et sans cache.

Lire deux rapports sans se tromper

Exemple fictif, sans lien avec les outils cités. Le jeu de référence contient 12 cas vulnérables et 12 cas sans la faille recherchée. Les deux moteurs analysent tous les fichiers. On compte une seule alerte par cas, après regroupement des doublons.

Un rapport plus court peut cacher davantage de failles.
MesureMoteur AMoteur B
Alertes à examiner816
Vraies failles trouvées8 sur 1211 sur 12
Fausses alertes05
Failles manquées41
Précision8 ÷ 8 = 100 %11 ÷ 16 ≈ 69 %
Rappel8 ÷ 12 ≈ 67 %11 ÷ 12 ≈ 92 %

A fournit moins d'alertes à examiner, mais manque quatre failles. Dans cet exemple, B retrouve les huit failles de A et trois autres. Il demande huit examens de plus : trois correspondent à des failles supplémentaires, cinq à de fausses alertes. Le choix dépend aussi de la nature des failles manquées et de votre capacité à traiter les résultats.

Ces pourcentages ne se transposent pas à votre dépôt, où les failles inconnues restent inconnues : le rappel se mesure sur vos cas de référence. Gardez les alertes indécises à part.

Le piège à éviter :zéro alerte avec zéro fichier analysé ne vaut pas un résultat propre. Et une précision de 100 % sur huit alertes ne signifie pas que toutes les failles sont trouvées.

Tester le travail après l'alerte

Prenez une vraie alerte du pilote et confiez-la à la personne qui devra la corriger. Peut-elle retrouver l'entrée, l'opération dangereuse et les étapes intermédiaires, expliquer le correctif et vérifier le comportement corrigé, au-delà de la seule disparition du signal ? Suivez ensuite le même défaut à travers une modification des lignes, une nouvelle analyse et une correction : l'historique doit rester rattaché au bon problème. Testez aussi une exception justifiée : qui l'approuve, quand expire-t-elle et que devient-elle si le code change ?

Si le fournisseur propose une correction par IA

Évaluez le correctif comme une modification de code : il doit supprimer la cause, préserver le comportement attendu et passer les tests. Un commentaire d'ignorance ou une règle désactivée peut faire disparaître l'alerte sans réparer le problème.

Demandez quel code et quel contexte sont transmis au modèle, où ils sont conservés, et si cette fonction peut être désactivée. Mesurez le temps de revue du correctif, pas seulement le temps nécessaire pour le générer.

Enfin, simulez une analyse interrompue ou incomplète dans le pilote. Le contrôle de livraison doit suivre la politique que vous avez choisie et expliquer l'échec. Un feu vert sans résultat exploitable fausse toute la comparaison.

Avant de signer

Fixez vos critères avant l'essai : langages indispensables, failles connues à retrouver, budget de tri et délai acceptable sur une modification. Un bon score global ne compense pas un langage essentiel non analysé. Testez un export SARIF dans l'outil qui recevra vos résultats : emplacements, traces et identifiants doivent rester exploitables. Les importateurs ne prennent pas tous en charge les mêmes champs, comme le montre la documentation GitHub. Vérifiez séparément la récupération des décisions, commentaires et responsables. Demandez enfin le coût total (licence, exécution, réglage, tri), les données transmises hors de votre environnement et leur durée de conservation. Notez les écarts à vos critères avant de décider.

Pour conclure

Un nombre d'alertes ne départage pas deux SAST. Ce qui compte : ce que l'outil a réellement lu, les failles connues qu'il retrouve sur votre code, le temps qu'il faut pour trancher chaque alerte, et ce qu'il fait quand il échoue. Fixez ces critères avant la démonstration, rejouez l'essai sur votre dépôt, et gardez la preuve.

Les mots de cet article · 4 mots
Banc d'essai (benchmark)
Un jeu de tests commun qui sert à comparer des outils.
Précision
La part des alertes d'un outil qui sont de vraies failles.
Rappel
La part des vraies failles qu'un outil trouve.
SARIF
Un format standard pour échanger les résultats d'analyse de code entre outils.

Pour revoir les bases : Le SAST expliqué simplement. Et pour les briques importées : Choisir un SCA sans se faire avoir.

Partager cet article

LinkedIn Bluesky X E-mail RSS

Pour commencer : SAST en profondeur : moteurs, taint et limites