Semgrep : analyse statique du code pour la sécurité
Mise à jour :
En 2022, un développeur découvre une injection SQL dans une application critique. Le code vulnérable existait depuis trois ans, relu par des dizaines de personnes. Un simple scan Semgrep aurait détecté le problème en quelques secondes. L’outil n’a pas besoin de comprendre la logique métier — il reconnaît les patterns dangereux.
Qu’est-ce que Semgrep ?
Semgrep est un outil d’analyse statique de code (SAST). Concrètement, il lit votre code source — sans l’exécuter — et cherche des patterns (modèles) qui correspondent à des vulnérabilités connues, des bugs ou des mauvaises pratiques.
Imaginez un correcteur orthographique, mais pour la sécurité du code. Au lieu de chercher des fautes d’orthographe, Semgrep cherche des constructions dangereuses comme :
# Semgrep détecte ce pattern dangereuxquery = "SELECT * FROM users WHERE id = " + user_inputcursor.execute(query) # ⚠️ Injection SQL possible !Le nom “Semgrep” vient de “semantic grep” : c’est comme la commande grep qui
cherche du texte, mais en comprenant la structure du code. Semgrep sait
qu’une variable est une variable, qu’une fonction est une fonction, etc.
Pourquoi utiliser Semgrep plutôt qu’un autre outil ?
Plusieurs scanners SAST existent sur le marché. Voici ce qui distingue Semgrep :
| Aspect | Semgrep | Scanners traditionnels |
|---|---|---|
| Règles | Fichiers YAML lisibles par un humain | Formats propriétaires, boîte noire |
| Vitesse | Très rapide (quelques secondes) | Souvent plusieurs minutes |
| Langages | 30+ supportés nativement | Variable selon l’outil |
| Faux positifs | Relativement peu | Souvent nombreux |
| Licence | Open source (LGPL 2.1) | Souvent commercial |
| Personnalisation | Écrire ses règles en 5 minutes | Complexe ou impossible |
Ce que Semgrep sait détecter
Semgrep est particulièrement efficace pour trouver :
Vulnérabilités de sécurité :
- Injections SQL : quand des données utilisateur sont insérées directement dans des requêtes de base de données
- Cross-Site Scripting (XSS) : quand des données utilisateur sont affichées sans être échappées dans une page web
- Command injection : quand des données utilisateur sont passées à des commandes système
- Path traversal : quand un attaquant peut accéder à des fichiers en dehors du répertoire prévu
Problèmes cryptographiques :
- Utilisation d’algorithmes obsolètes (MD5, SHA1 pour les mots de passe)
- Clés de chiffrement ou mots de passe en dur dans le code
- Générateurs de nombres aléatoires non sécurisés
Mauvaises pratiques :
- Utilisation de
eval()ou équivalent - Désactivation de la vérification SSL
- Permissions trop larges
- Code qui ne gère pas les erreurs correctement
Installation
Semgrep s’installe en une seule commande. Choisissez la méthode qui correspond à votre environnement.
Si vous avez Python installé (version 3.8 ou supérieure), c’est la méthode la plus simple :
pip install semgrepCette commande télécharge Semgrep et toutes ses dépendances. L’installation prend généralement moins d’une minute.
Pour vérifier que tout fonctionne :
semgrep --versionVous devriez voir quelque chose comme semgrep 1.145.2.
Sur macOS, Homebrew est souvent le gestionnaire de paquets le plus pratique :
brew install semgrepHomebrew télécharge une version précompilée, l’installation est donc rapide.
Vérification :
semgrep --versionSi vous préférez ne rien installer sur votre machine, Docker est une bonne option. L’image officielle contient tout le nécessaire :
docker pull returntocorp/semgrepPour scanner un projet avec Docker, il faut monter le répertoire courant dans le conteneur :
docker run --rm -v "${PWD}:/src" returntocorp/semgrep \ semgrep --config=auto /srcExplication de la commande :
--rm: supprime le conteneur après exécution-v "${PWD}:/src": monte le répertoire courant dans/srcdu conteneur/src: chemin à scanner (notre code monté)
Si vous utilisez asdf-vm pour gérer vos outils :
asdf plugin add semgrepasdf install semgrep latestasdf set --home semgrep latestVérification :
semgrep --version1.145.2Premier scan : découvrir Semgrep
Maintenant que Semgrep est installé, lançons un premier scan pour voir comment il fonctionne.
Le mode automatique
La façon la plus simple de démarrer est d’utiliser le mode auto. Semgrep
détecte automatiquement les langages présents dans votre projet et applique
les règles appropriées :
cd /chemin/vers/mon-projetsemgrep scan --config=auto .Que fait cette commande ?
- Semgrep parcourt tous les fichiers du répertoire courant (
.) - Il identifie les langages (Python, JavaScript, Go, etc.)
- Il télécharge les règles adaptées depuis le registre Semgrep
- Il analyse chaque fichier et affiche les problèmes trouvés
Lors du premier scan, Semgrep affiche un résumé détaillé :
┌──── ○○○ ────┐│ Semgrep CLI │└─────────────┘
Scanning 35 files (only git-tracked) with 327 Code rules:
CODE RULES
Language Rules Files Origin Rules ───────────────────────────── ─────────────────── <multilang> 2 35 Community 327 python 151 15 json 1 2
SUPPLY CHAIN RULES
💎 Sign in with `semgrep login` and run `semgrep ci` to find dependency vulnerabilities and advanced cross-file findings.
PROGRESS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
┌──────────────┐│ Scan Summary │└──────────────┘✅ Scan completed successfully. • Findings: 0 (0 blocking) • Rules run: 154 • Targets scanned: 35Ce résumé indique que vous utilisez Semgrep OSS (la version open source gratuite). Les fonctionnalités Supply Chain et cross-file nécessitent un compte — nous y reviendrons en fin de guide.
Le premier scan peut prendre quelques secondes supplémentaires car Semgrep télécharge les règles. Les scans suivants seront plus rapides grâce au cache.
Comprendre les résultats
Quand Semgrep trouve un problème, il affiche un rapport détaillé. Voici un exemple réel de sortie sur un projet Python :
┌──────────────────┐│ 1 Code Finding │└──────────────────┘
src/utils/sitemap_utils.py ❯❱ python.lang.security.use-defused-xml.use-defused-xml The Python documentation recommends using `defusedxml` instead of `xml` because the native Python `xml` library is vulnerable to XML External Entity (XXE) attacks. These attacks can leak confidential data and "XML bombs" can cause denial of service.
3┆ from xml.etree import ElementTree
Severity: ERROR Details: https://semgrep.dev/r/python.lang.security...Décortiquons ce rapport :
| Élément | Signification |
|---|---|
python.lang.security.use-defused-xml.use-defused-xml | Identifiant unique de la règle qui a déclenché l’alerte |
| Message explicatif | Ce que Semgrep a trouvé et pourquoi c’est un problème |
3┆ | Le numéro de la ligne concernée dans votre fichier |
| Code affiché | L’extrait de code problématique |
Severity: ERROR | Niveau de gravité (INFO, WARNING, ERROR) |
Details: ... | Lien vers la documentation de la règle |
Les niveaux de sévérité
Semgrep utilise trois niveaux de sévérité :
| Niveau | Signification | Action recommandée |
|---|---|---|
| ERROR | Problème critique, probablement une vraie vulnérabilité | Corriger immédiatement |
| WARNING | Problème potentiel, à investiguer | Analyser et corriger si confirmé |
| INFO | Information, bonne pratique non respectée | Amélioration suggérée |
Scanner avec des règles spécifiques
Le mode auto est pratique pour débuter, mais vous voudrez souvent utiliser
des packs de règles spécifiques selon votre objectif.
Qu’est-ce qu’un pack de règles ?
Un pack est un ensemble de règles regroupées par thème. Semgrep fournit des
packs maintenus par la communauté et l’équipe Semgrep. Les packs commencent
par p/ (pour “pack”).
Les packs les plus utiles
Pour la sécurité :
# OWASP Top 10 : les 10 vulnérabilités web les plus courantessemgrep scan --config=p/owasp-top-ten .
# Audit de sécurité complet : règles plus exhaustivessemgrep scan --config=p/security-audit .
# Détection de secrets (mots de passe, clés API)semgrep scan --config=p/secrets .Par langage :
# Python : sécurité + qualité de codesemgrep scan --config=p/python .
# JavaScript/TypeScriptsemgrep scan --config=p/javascript .
# Gosemgrep scan --config=p/golang .
# Javasemgrep scan --config=p/java .Pour la CI/CD :
# Pack optimisé pour les pipelines (rapide, peu de faux positifs)semgrep scan --config=p/ci .Combiner plusieurs packs
Vous pouvez appliquer plusieurs packs en même temps :
semgrep scan --config=p/security-audit --config=p/secrets .Cette commande applique les règles de sécurité générales ET les règles de détection de secrets.
Le registre de règles
Semgrep dispose d’un registre public contenant plus de 2000 règles écrites par la communauté et l’équipe Semgrep.
Explorer le registre
Rendez-vous sur semgrep.dev/explore ↗ pour parcourir les règles disponibles. Vous pouvez :
- Filtrer par langage (Python, JavaScript, Go, etc.)
- Filtrer par catégorie (sécurité, qualité, performance)
- Rechercher par mot-clé (sql injection, xss, etc.)
- Voir le code source de chaque règle
Utiliser une règle spécifique
Si vous trouvez une règle intéressante, vous pouvez l’utiliser directement par son identifiant. Sur la page de la règle dans le registre, cliquez sur “Run Locally” pour obtenir la commande exacte :
# Utiliser une règle spécifique du registre (préfixe r/)semgrep scan --config="r/python.lang.security.audit.dangerous-system-call" .Écrire ses propres règles
L’une des forces de Semgrep est la facilité avec laquelle on peut écrire des règles personnalisées. Les règles sont des fichiers YAML lisibles.
Anatomie d’une règle
Voici une règle simple qui détecte l’utilisation de eval() en Python :
rules: - id: dangerous-eval-usage patterns: - pattern: eval($X) message: | Utilisation de eval() détectée. La fonction eval() exécute du code Python arbitraire. Si l'argument provient d'une entrée utilisateur, un attaquant pourrait exécuter n'importe quel code sur le serveur.
Alternatives sécurisées : - ast.literal_eval() pour parser des structures de données simples - json.loads() pour du JSON - Un parser dédié pour votre format de données severity: WARNING languages: - python metadata: category: security cwe: "CWE-95: Improper Neutralization of Directives" references: - https://owasp.org/www-community/attacks/Code_InjectionExplication de chaque champ :
| Champ | Obligatoire | Description |
|---|---|---|
id | Oui | Identifiant unique de la règle |
patterns | Oui | Ce que Semgrep doit chercher dans le code |
pattern | - | Le pattern à matcher (ici eval($X)) |
$X | - | Variable qui capture n’importe quel argument |
message | Oui | Explication affichée quand la règle matche |
severity | Oui | INFO, WARNING ou ERROR |
languages | Oui | Liste des langages concernés |
metadata | Non | Informations supplémentaires (CWE, références) |
Utiliser une règle personnalisée
Enregistrez votre règle dans un fichier, par exemple rules/custom.yaml, puis :
semgrep scan --config=rules/custom.yaml .Vous pouvez aussi combiner règles personnalisées et packs :
semgrep scan --config=rules/custom.yaml --config=p/security-audit .Exemple : détecter les injections SQL
Voici une règle plus avancée pour détecter les injections SQL en Python :
rules: - id: sql-injection-python patterns: - pattern-either: # String formatting avec % - pattern: cursor.execute($QUERY % ...) # String formatting avec .format() - pattern: cursor.execute($QUERY.format(...)) # f-strings - pattern: cursor.execute(f"...") # Concaténation de strings - pattern: cursor.execute($QUERY + ...) # Exclure les requêtes paramétrées (qui sont sécurisées) - pattern-not: cursor.execute($QUERY, ...) - pattern-not: cursor.execute($QUERY, $PARAMS) message: | Possible injection SQL détectée. La requête SQL est construite par concaténation ou formatage de strings, ce qui permet à un attaquant d'injecter du code SQL malveillant.
❌ Vulnérable : cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
✅ Sécurisé (requête paramétrée) : cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,)) severity: ERROR languages: - python metadata: category: security cwe: "CWE-89: SQL Injection"Cette règle utilise plusieurs opérateurs de patterns :
| Opérateur | Ce qu’il fait |
|---|---|
pattern-either | Matche si l’un des patterns est présent |
pattern-not | Exclut les cas qui matchent ce pattern |
pattern | Pattern simple à matcher |
Tester une règle avant de l’utiliser
Semgrep fournit un playground en ligne pour tester vos règles : semgrep.dev/playground ↗
Vous pouvez y coller votre règle YAML et du code de test pour vérifier qu’elle détecte bien ce que vous voulez (et ne génère pas de faux positifs).
Intégration dans le pipeline CI/CD
Le vrai pouvoir de Semgrep apparaît quand il s’exécute automatiquement à chaque modification de code. Voici comment l’intégrer dans les pipelines les plus courants.
GitHub Actions
Créez le fichier .github/workflows/semgrep.yml :
name: Semgrep Security Scan
on: # Scanner à chaque pull request pull_request: {} # Scanner les pushs sur main push: branches: - main
jobs: semgrep: name: Analyse de sécurité runs-on: ubuntu-latest container: image: returntocorp/semgrep
steps: # Récupérer le code - name: Checkout du code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Lancer le scan - name: Scan Semgrep run: | semgrep --config=p/security-audit \ --error \ --json \ -o semgrep-results.json \ .
# Sauvegarder les résultats même si le scan échoue - name: Upload des résultats uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: always() with: name: semgrep-results path: semgrep-results.jsonExplication des options :
--config=p/security-audit: utilise le pack de sécurité--error: fait échouer le workflow si des problèmes sont trouvés--json -o semgrep-results.json: génère un rapport JSONif: always(): sauvegarde les résultats même si le scan a échoué
GitLab CI
Ajoutez ce job dans votre .gitlab-ci.yml :
semgrep: stage: test image: returntocorp/semgrep script: - semgrep --config=p/security-audit --error --json -o semgrep.json . artifacts: paths: - semgrep.json when: always expire_in: 1 week rules: # Scanner les merge requests - if: $CI_PIPELINE_SOURCE == "merge_request_event" # Scanner la branche par défaut - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCHPre-commit : scanner avant chaque commit
Pour détecter les problèmes encore plus tôt, vous pouvez configurer Semgrep comme hook pre-commit. Ainsi, le code est scanné avant d’être commité.
Créez ou modifiez .pre-commit-config.yaml :
repos: - repo: https://github.com/returntocorp/semgrep rev: v1.51.0 hooks: - id: semgrep args: ['--config', 'p/security-audit', '--error']Puis installez le hook :
pip install pre-commitpre-commit installDésormais, chaque git commit déclenchera un scan Semgrep. Si des problèmes
sont trouvés, le commit sera bloqué.
Gérer les faux positifs
Comme tout outil d’analyse statique, Semgrep peut parfois signaler du code qui n’est pas réellement vulnérable. C’est un faux positif. Voici comment les gérer.
Ignorer une occurrence spécifique
Si Semgrep signale une ligne qui est en fait sûre, vous pouvez l’ignorer avec
un commentaire nosemgrep :
# L'entrée est validée en amont, cette utilisation est sûreresult = eval(validated_expression) # nosemgrep: dangerous-eval-usageVous pouvez aussi ignorer toutes les règles sur une ligne :
result = eval(validated_expression) # nosemgrepBonne pratique : ajoutez toujours un commentaire expliquant pourquoi vous ignorez l’alerte. Cela aide les futurs relecteurs à comprendre votre décision.
Exclure des fichiers ou dossiers
Certains fichiers ne devraient pas être scannés : tests, code généré,
dépendances vendorisées, etc. Créez un fichier .semgrepignore à la racine
du projet :
# Fichiers de tests (souvent avec du code volontairement vulnérable)tests/*_test.pytest_*.pyspec/
# Code généré automatiquementgenerated/*.pb.go*.generated.ts
# Dépendances vendoriséesvendor/node_modules/third_party/
# Fichiers de configuration*.config.jsLe format est similaire à .gitignore.
Exclure via la ligne de commande
Pour exclure des chemins ponctuellement sans modifier .semgrepignore :
semgrep scan --config=p/security-audit \ --exclude="tests/*" \ --exclude="vendor/*" \ --exclude="*.test.js" \ .Stratégie de déploiement progressive
Activer Semgrep en mode bloquant du jour au lendemain sur un projet existant va générer beaucoup d’alertes et frustrer les équipes. Voici une approche progressive qui fonctionne.
-
Phase 1 : Observer (1-2 semaines)
Lancez Semgrep sans bloquer, juste pour voir l’état actuel :
Terminal window semgrep scan --config=p/security-audit . > rapport-initial.txtAnalysez les résultats. Combien d’alertes ? Combien de vrais problèmes vs faux positifs ? Cela vous donne une baseline.
-
Phase 2 : Alerter (2-4 semaines)
Intégrez Semgrep en CI/CD mais sans bloquer. Affichez les résultats dans les logs ou envoyez-les sur Slack :
Terminal window semgrep scan --config=p/security-audit --json . | \jq '.results | length'# Résultat : 1L’équipe commence à voir les alertes et à s’y habituer.
-
Phase 3 : Bloquer les critiques
Faites échouer le pipeline uniquement sur les erreurs critiques :
Terminal window semgrep scan --config=p/security-audit --severity=ERROR --error .Les WARNING et INFO sont toujours affichés mais ne bloquent pas.
-
Phase 4 : Bloquer tout
Une fois que l’équipe est à l’aise et que les faux positifs sont gérés :
Terminal window semgrep scan --config=p/security-audit --error .Tous les nouveaux problèmes bloquent le pipeline. Les anciens problèmes sont soit corrigés, soit marqués comme ignorés avec une justification.
Formats de sortie
Semgrep peut générer ses résultats dans différents formats selon vos besoins.
Texte (défaut)
Format lisible par un humain, idéal pour le terminal :
semgrep scan --config=p/security-audit .JSON
Format structuré pour traitement automatisé (scripts, dashboards) :
semgrep scan --config=p/security-audit --json -o results.json .Le fichier JSON contient tous les détails : fichier, ligne, règle, message, sévérité, etc.
SARIF
Format standard pour les outils de sécurité, supporté nativement par GitHub Code Scanning et GitLab SAST :
semgrep scan --config=p/security-audit --sarif -o results.sarif .Pour l’intégrer à GitHub Code Scanning :
- name: Scan Semgrep run: semgrep scan --config=p/security-audit --sarif -o semgrep.sarif .
- name: Upload vers GitHub Security uses: github/codeql-action/upload-sarif@v3 with: sarif_file: semgrep.sarifLes résultats apparaîtront dans l’onglet Security de votre repository GitHub.
JUnit XML
Format compatible avec les outils CI classiques (Jenkins, etc.) :
semgrep scan --config=p/security-audit --junit-xml -o results.xml .Semgrep Cloud (version payante)
Tout ce que nous avons vu jusqu’ici concerne la version open source gratuite de Semgrep. Elle couvre la grande majorité des besoins.
Semgrep AppSec Platform (anciennement Semgrep App / Semgrep Cloud) est la version payante qui ajoute des fonctionnalités entreprise. Elle inclut plusieurs produits :
- Semgrep Code : SAST avancé avec analyse inter-fichiers
- Semgrep Supply Chain : SCA pour analyser les dépendances
- Semgrep Secrets : détection et validation de secrets
Ce que vous avez gratuitement
La version open source inclut :
- Le scanner CLI complet, sans limitation
- Accès aux 2000+ règles du registre communautaire
- Création de règles personnalisées illimitées
- Intégration CI/CD (GitHub, GitLab, Jenkins, etc.)
- Tous les formats de sortie (JSON, SARIF, JUnit)
- Support communautaire (GitHub Issues, Slack)
Pour la plupart des équipes, c’est suffisant.
Ce qu’ajoute Semgrep Cloud
| Fonctionnalité | Description | Utile pour |
|---|---|---|
| Dashboard centralisé | Vue unifiée des findings de tous vos repos | Équipes avec beaucoup de projets |
| Gestion des findings | Triage, assignation, workflow de remédiation | Suivi des corrections |
| Règles Pro | Règles exclusives plus précises et complètes | Moins de faux positifs |
| Historique | Tendances, métriques dans le temps | Reporting direction |
| Intégrations | Jira, Slack, webhooks | Workflow d’équipe |
| SSO/SAML | Authentification entreprise | Conformité |
| Support dédié | Aide technique prioritaire | Grandes équipes |
Tarification (décembre 2024)
| Plan | Prix | Inclus |
|---|---|---|
| Community Edition | Gratuit | OSS SAST, règles communautaires, jusqu’à 10 contributeurs |
| Teams - Code (SAST) | $40/mois/contributeur | Pro Engine, règles Pro, analyse cross-file |
| Teams - Supply Chain (SCA) | $40/mois/contributeur | Analyse des dépendances, SBOM, licences |
| Teams - Secrets | $20/mois/contributeur | Détection et validation de secrets |
| Enterprise | Sur devis | Tout Teams + account manager, onboarding, roadmap |
Quand passer à la version payante ?
Semgrep Cloud devient pertinent quand :
- Vous gérez plusieurs dizaines de repositories
- Vous avez besoin de reporting centralisé pour la direction ou l’audit
- Vos processus de conformité exigent un historique et des preuves
- Vous voulez réduire les faux positifs avec les règles Pro
- Votre équipe a besoin d’un workflow de remédiation structuré
Pour une équipe de quelques développeurs sur quelques projets, la version gratuite suffit amplement.
Limites de Semgrep
Comme tout outil, Semgrep a des limites qu’il faut connaître :
Ce que Semgrep ne fait pas :
- Analyse dynamique : Semgrep ne détecte pas les failles qui apparaissent uniquement à l’exécution (utilisez le DAST pour ça)
- Flow analysis complexe : certaines failles qui nécessitent de suivre les données à travers de nombreuses fonctions peuvent échapper à Semgrep
- Failles de configuration : les problèmes dans les fichiers de config serveur ou cloud ne sont pas détectés (sauf pour les fichiers IaC supportés)
- Analyse des dépendances : Semgrep ne scanne pas les vulnérabilités dans vos dépendances (utilisez le SCA pour ça)
Couverture variable selon les langages :
Les langages les plus populaires (Python, JavaScript, Go, Java) ont beaucoup de règles. Les langages moins courants peuvent avoir une couverture plus limitée.
Nécessite une maintenance :
Les règles personnalisées doivent être maintenues quand le code évolue. Les règles du registre sont maintenues par la communauté et l’équipe Semgrep.
Pour aller plus loin
Autres guides de ce site
- SAST : comprendre l’analyse statique — Vue d’ensemble du SAST et comparaison des approches
- DAST : tests dynamiques — Compléter Semgrep avec des tests en runtime
- SCA : analyse des dépendances — Scanner les vulnérabilités dans les bibliothèques
- Gitleaks — Détection de secrets dans l’historique Git
- TruffleHog — Scanner de secrets avancé
Ressources officielles
- Documentation Semgrep ↗ — Guide officiel complet
- Registre de règles ↗ — Explorer les 2000+ règles disponibles
- Playground ↗ — Tester des règles en ligne
- GitHub Semgrep ↗ — Code source et issues