Aller au contenu principal

SAST

fremforge exécute OpenGrep sur chaque pull request et sur la branche par défaut de chaque dépôt. Il tourne sur les analyseurs propres à fremforge : il n’y a donc aucun fichier de workflow à ajouter. Une pull request reçoit le statut fremforge/sast et un commentaire. Les résultats sont listés sous Sécurité › Résultats › SAST (/<org>/_admin/security/findings/sast).

Langages

C, C++, C#, Go, Java, JavaScript et TypeScript, Kotlin, PHP, Python, Ruby, Rust, Scala, Swift et Bash.

Règles

Quatre jeux de règles sont intégrés à l’image de l’analyseur. Rien n’est récupéré pendant une analyse :

  • les GitLab sast-rules : uniquement ses dossiers de règles par langage, pour C#, Go, Java, JavaScript, Python et Scala. Elles sont sous licence MIT, sauf les règles Go, dérivées de gosec et sous licence Apache-2.0 ;
  • les règles 0xdea pour C et C++, sous licence MIT ;
  • les règles propres à fremforge, sous licence MIT, pour JavaScript et TypeScript, Bash, PHP, Ruby, Rust, Kotlin et Swift ;
  • les règles de taint propres à fremforge, sous licence MIT, pour Python, JavaScript et TypeScript, Java, C# et Go.

Le dépôt GitLab contient aussi du contenu sous d’autres licences, que fremforge ne livre pas. Le build de l’image conserve un ensemble autorisé, les dossiers de règles par langage, et supprime le reste. Il vérifie ensuite chaque fichier conservé et échoue si l’un d’eux porte une licence autre que MIT, Apache-2.0 ou BSD.

Règles de taint

Les règles de taint de fremforge suivent les données de requête depuis leur point d’entrée dans votre code (un paramètre de requête, un champ de formulaire, un en-tête, un cookie, un corps de requête) jusqu’à l’endroit où elles peuvent nuire, et signalent le chemin entre les deux. Elles couvrent l’injection SQL, l’injection de commande et de code, la traversée de répertoires, la falsification de requête côté serveur (SSRF), le cross-site scripting et la désérialisation non sûre en Python, JavaScript et TypeScript, Java, C# et Go. Elles connaissent les objets de requête de Flask, Django, FastAPI, aiohttp, Express, Koa, Hono, Next.js, Servlet, Spring, JAX-RS, ASP.NET Core, net/http, gin, echo et fiber. Une valeur qui passe en chemin par une fonction d’assainissement (un échappement HTML, une réduction à un nom de fichier, un paramètre SQL lié, une conversion en nombre) n’est pas signalée.

Ce qu’elles suivent, et ce qu’elles ne suivent pas :

  • les données au sein d’une fonction, et entre fonctions d’un même fichier ;
  • pas les données qui quittent un fichier et reviennent dans un autre ;
  • pas quelle branche d’un if s’exécute, ni quelle clé d’une map ou quel indice d’une liste contient une valeur : une valeur protégée par une vérification toujours vraie peut quand même être signalée ;
  • aucun modèle des bibliothèques tierces au-delà des sources, puits et fonctions d’assainissement que nomment les règles ;
  • les fichiers de test et de spec sont exclus.

Chaque résultat porte le chemin de la source au puits. Elles sont activées pour les organisations propres à fremforge et désactivées pour les autres le temps que leur taux de faux positifs soit mesuré, et leurs résultats sont listés mais ne bloquent jamais une fusion, quelle que soit leur gravité. Lorsqu’un résultat de taint et un résultat d’une autre règle se trouvent sur la même ligne pour la même faiblesse (CWE), seul le résultat de taint est listé. Activez-les ou désactivez-les avec le paramètre taint_rules ci-dessous.

Vos propres règles

Une organisation peut ajouter ses propres règles OpenGrep. fremforge/sast les exécute avec les jeux de règles intégrés sur chaque pull request et sur la branche par défaut de chaque dépôt, avec le même mode et la même gravité de blocage, et sur une pull request seul ce qu’elle ajoute la bloque.

Ajoutez-les sous Sécurité › Politiques › Règles SAST, via l’API, ou avec Terraform (ci-dessous). Chaque règle est un YAML contenant exactement une règle sous rules:, et un échantillon de test : du code que la règle doit trouver.

rules:
  - id: acme-no-eval
    message: Do not pass data to eval(); use ast.literal_eval or a parser.
    severity: ERROR
    languages: [python]
    pattern: eval(...)

Une règle doit avoir :

  • un id de 2 à 63 lettres minuscules, chiffres et tirets, unique dans l’organisation (ses résultats apparaissent sous custom/<id>) ;
  • un message, une severity (ERROR, WARNING ou INFO, affichées comme élevée, moyenne et faible) et de 1 à 5 languages : Bash, C, C++, C#, Dockerfile, generic, Go, HTML, Java, JavaScript, JSON, Kotlin, PHP, Python, Ruby, Rust, Scala, Swift, Terraform, TypeScript ou YAML ;
  • un motif : pattern, patterns, pattern-either ou pattern-regex, ou mode: taint avec pattern-sources et pattern-sinks.

Seules les clés de motif, de métavariable, de taint, paths, fix, options et metadata sont autorisées, si bien qu’une règle ne peut pas agir en dehors d’elle-même. Les ancres et alias YAML sont refusés. Au plus 50 règles par organisation, de 16 Kio chacune, avec un échantillon de test d’au plus 16 Kio.

Une règle enregistrée est En vérification tant que l’analyseur ne l’a pas exécutée, avec le même opengrep et dans le même environnement cloisonné que vos analyses, sur son propre échantillon de test. Elle devient Actif lorsqu’elle se charge correctement, trouve quelque chose dans l’échantillon et se termine en moins de 30 secondes (5 secondes par fichier) ; sinon elle est Rejeté, avec la raison. Seule une règle active qui n’est pas désactivée s’exécute. Modifier une règle ou son échantillon la vérifie à nouveau ; d’ici là, elle ne s’exécute pas. Vous pouvez désactiver une règle sans la supprimer.

Les résultats de vos règles apparaissent avec les résultats intégrés, dans la vérification de pull request et sous Sécurité › Résultats › SAST, marqués Personnalisé avec le nom de la règle. Ils bloquent comme les résultats intégrés : selon leur gravité par rapport à la gravité de blocage ci-dessous.

Les règles sont stockées dans fremforge et exécutées depuis fremforge. L’analyseur ne récupère jamais de règles depuis une URL ou un registre, et la vérification d’une règle n’effectue aucun appel réseau. Le paramètre custom_rules_url est retiré : il n’est plus lu, et une valeur autre que null ou "" est refusée avec custom-rules-url-removed.

API

GET    /_app/api/v1/orgs/{org}/code-security/sast/custom-rules
GET    /_app/api/v1/orgs/{org}/code-security/sast/custom-rules/{id}
POST   /_app/api/v1/orgs/{org}/code-security/sast/custom-rules       { "name": "No eval", "source": "<yaml>", "sample": "<code>", "enabled": true }
PUT    /_app/api/v1/orgs/{org}/code-security/sast/custom-rules/{id}
DELETE /_app/api/v1/orgs/{org}/code-security/sast/custom-rules/{id}

La liste nécessite findings:read ; les modifications nécessitent policy:write. Une règle nouvelle ou modifiée revient avec le status pending ; le verdict de l’analyseur le passe à valid ou invalid, avec status_code (par exemple no-match ou parse), status_detail (le message propre à opengrep, lorsqu’il y en a un) et status_reason (une phrase). Une règle que l’API peut refuser avant que l’analyseur ne la voie reçoit une réponse 400 avec la raison (par exemple one-rule ou unknown-key) ; un id déjà utilisé donne duplicate-id et la 51e règle limit-reached, toutes deux en 409. Chaque modification figure dans le journal d’audit.

Terraform et OpenTofu

Chaque règle est une ressource fremforge_sast_custom_rule (provider 0.5.0 et ultérieur). Un apply attend le verdict de l’analyseur et échoue avec la raison lorsque la règle est rejetée ; définissez wait_for_verdict = false pour ne pas attendre.

resource "fremforge_sast_custom_rule" "no_eval" {
  org    = "acme"
  name   = "No eval"
  source = file("sast/no-eval.yaml")
  sample = file("sast/no-eval.sample.py")
}

custom_rules_url sur fremforge_sast_settings est obsolète et n’est plus envoyé ; supprimez-le.

Paramètres

Sous Sécurité › Résultats › SAST, ou via GET et PUT /_app/api/v1/orgs/{org}/code-security/sast/settings (PUT nécessite policy:write) :

ParamètreValeursPar défaut
SAST activé pour cette organisationactivé, désactivéactivé
Gravité de blocageinfo, warning, error : les résultats de ce niveau ou au-dessus font échouer fremforge/sasterror
Règles de taint (taint_rules)default, on, off. default est activé pour les organisations propres à fremforge et désactivé pour les autres. Leurs résultats ne bloquent jamaisdefault

Qu’une vérification en échec bloque ou non une fusion dépend aussi du mode de la vérification sous Sécurité › Prioriser › Vérifications des pull requests et de la protection de branche. Sur une pull request, seuls les résultats introduits par la pull request bloquent : un résultat qui a seulement changé de ligne n’est pas nouveau.

Résultats

Les résultats sont classés par niveau de confiance, puis par gravité, puis selon que l’analyseur a suivi des données depuis une source telle qu’une entrée utilisateur jusqu’au résultat, puis par ancienneté. Les résultats dans les tests, les exemples, le code tiers ou généré, et les résultats d’une règle souvent ignorée, sont listés plus bas ; ils ne sont pas ignorés. Ignorez un résultat avec une raison, un par un ou en masse, ou avec POST .../code-security/sast/findings/{id}/dismiss. La liste est aussi disponible via GET /_app/api/v1/orgs/{org}/code-security/sast/findings.

Correctifs IA

Pour une courte liste de règles, Correctif IA demande au modèle d’IA de votre organisation une pull request de correctif. Il est désactivé par défaut ; activez-le sous Sécurité › Corriger › Correctif IA. Voir Correctifs IA pour les résultats SAST.

Voir aussi