Aller au contenu principal

Python · SAST

SAST Python qui tourne entièrement hors-ligne

Auditez votre code Python pour les vulnérabilités OWASP Top 10, les misconfigurations spécifiques aux frameworks et les risques de dépendances — sans envoyer une seule ligne au cloud. Couvre Django, Flask, FastAPI, SQLAlchemy et la stdlib.

Frameworks & bibliothèques scannés

Nous testons la couverture sur ces frameworks via fixtures. De nouveaux patterns sont ajoutés à chaque release de règles builtin.

Django Flask FastAPI SQLAlchemy Pyramid Tornado aiohttp Starlette Pandas NumPy Requests urllib3 PyYAML paramiko cryptography pyjwt

Principales classes CWE détectées

Ces classes CWE apparaissent le plus souvent dans les codebases modernes de ce langage. StaticCodeAudit livre des règles dédiées pour chacune, mappées à OWASP Top 10 / ISO 27001 / ASVS quand pertinent.

CWE-89

Injection SQL

Concaténation ou f-strings utilisés pour construire des requêtes SQL — typique avec cursor.execute(f"SELECT ... {user_input}"), Django .raw() avec concat, ou SQLAlchemy .text() sans paramètres liés.

Détecté par la règle SCA : sql_injection_fstring

CWE-78

Injection de commande OS

subprocess.run(shell=True, ...), os.system() avec entrée utilisateur. Le flag shell=True permet l\'abus des métacaractères shell.

Détecté par la règle SCA : os_system_injection

CWE-502

Désérialisation non sécurisée

pickle.loads(), yaml.load() sans SafeLoader, shelve, ou marshal sur des bytes non fiables. Équivalent à une exécution de code à distance.

Détecté par la règle SCA : unsafe_deserialization

CWE-918

SSRF

requests.get(user_url), urllib.request.urlopen() sur des URLs contrôlées par l\'utilisateur sans allow-list de schéma/hôte. Permet d\'atteindre des services internes (endpoints metadata, RDS, etc.).

Détecté par la règle SCA : taint_ssrf

CWE-798

Identifiants en dur

Clés API, secrets JWT, mots de passe DB dans les sources. Détectés par entropie + patterns connus (AWS, Stripe, GitHub, Slack, etc.).

Détecté par la règle SCA : hardcoded_secret

CWE-94

Injection de code via compilation dynamique

Appels aux built-ins de compilation dynamique de Python sur des données partiellement contrôlées par l\'utilisateur.

Détecté par la règle SCA : dangerous_eval

Vulnérable vs. sain — trois exemples rapides

CWE-89 Détecté par la règle SCA : sql_injection_fstring
❌ Vulnérable
# Vulnérable — Flask + SQLAlchemy raw
@app.route('/user/<name>')
def user(name):
    sql = f"SELECT * FROM users WHERE name = '{name}'"
    return db.engine.execute(sql).fetchone()
✅ Sain
# Sain — paramètre lié
@app.route('/user/<name>')
def user(name):
    sql = text("SELECT * FROM users WHERE name = :name")
    return db.engine.execute(sql, {"name": name}).fetchone()
CWE-78 Détecté par la règle SCA : os_system_injection
❌ Vulnérable
# Vulnérable — shell=True avec entrée utilisateur
import subprocess
def ping(host):
    return subprocess.run(f"ping -c 1 {host}", shell=True)
✅ Sain
# Sain — liste d'arguments, sans shell
import subprocess
def ping(host):
    return subprocess.run(["ping", "-c", "1", host], check=False)
CWE-502 Détecté par la règle SCA : unsafe_deserialization
❌ Vulnérable
# Vulnérable — yaml.load sans SafeLoader
import yaml
def load_config(blob):
    return yaml.load(blob)  # Loader complet = RCE
✅ Sain
# Sain — yaml.safe_load
import yaml
def load_config(blob):
    return yaml.safe_load(blob)

Ce que StaticCodeAudit détecte (ce langage)

  • Injection SQL en SQL brut, f-strings, .format(), Django .raw(), SQLAlchemy .text() sans paramètres liés
  • Injection de commande OS (subprocess avec shell=True, os.system, os.popen)
  • Désérialisation non sécurisée (pickle, yaml.load, marshal, shelve)
  • SSRF via requests, urllib, aiohttp sur URLs contrôlées par l'utilisateur
  • Secrets en dur (AWS, Stripe, GitHub PAT, tokens Slack, secrets JWT, mots de passe DB, clés PEM)
  • XXE et billion-laughs XML (xml.etree, lxml sans resolver désactivé)
  • Path traversal (os.path.join avec entrée utilisateur, open() sans ancrage racine)
  • Cookies non sécurisés (flags Flask/Django Secure / HttpOnly / SameSite manquants)
  • CSRF exempté (@csrf_exempt, Flask sans flask-wtf)
  • Crypto non sécurisée (MD5/SHA1 pour sécurité, mode ECB, IV en dur, random faible)
  • Mode debug activé en production Flask / Django
  • JWT non sécurisé (algorithme none, secret en dur, pas d'expiration)
  • APIs dépréciées (PyCrypto, ssl.TLSv1, style urllib2)
  • PII dans les logs et messages d'exception
  • Misconfigurations CI/CD (.gitlab-ci.yml, GitHub Actions : checkout non fiable, secrets en logs)

Envie de savoir comment la qualité de détection est réellement mesurée ? Consultez la méthodologie complète des benchmarks multi-langages (OWASP Benchmark, NIST Juliet, précision/recall/F1 par langage) →

OWASP Benchmark (Python) — validation indépendante

StaticCodeAudit a été mesuré sur l'OWASP Benchmark (Python), un benchmark public et reproductible de 1 230 cas de test Python — complété par une vérification réelle sur 3 frameworks reconstruits à partir de CVE publiées.

86,5 %
Score F1
96,0 %
Rappel
1 230
Cas de test

CVE Test Suite, par framework — 2 frameworks sur 3 à F1 = 100 %

100 %
Flask (reconstitué depuis CVE)
100 %
Django (reconstitué depuis CVE)
80,0 %
stdlib Python (reconstitué depuis CVE)

OWASP Benchmark Python affiche 78,8 % de précision pour 96,0 % de rappel (1 230 cas, méthodologie indépendante) — les vraies failles sont signalées, au prix de quelques faux positifs. Les 3 lignes ci-dessus proviennent d'un test séparé et plus dur : 45 cas reconstitués à partir de CVE réelles et historiques, sur 8 frameworks et 5 langages. Les 3 frameworks Python y obtiennent le meilleur score ; détail complet (y compris les langages moins bien notés) sur la <a href="/fr/language-benchmarks.php" class="text-primary font-semibold hover:underline">page des benchmarks par langage</a>.

Les vraies failles tiennent rarement dans un seul fichier

Les applications Flask et Django répartissent la logique en couches : une vue reçoit la requête, une fonction d'accès aux données construit la requête SQL. Un scanner limité à un seul fichier à la fois ne fait jamais le lien — il voit la donnée utilisateur dans views.py et l'appel base de données dans db.py, mais jamais la connexion entre les deux. StaticCodeAudit suit la donnée à travers les fichiers.

views.py
@app.route("/orders")
def find_order():
    order_id = request.args.get("id")
    return jsonify(get_order(order_id))
db.py
def get_order(order_id):
    sql = f"SELECT * FROM orders WHERE id = {order_id}"
    return db.execute(sql).fetchone()

order_id provient de la requête HTTP dans la vue, et atteint la requête SQL un fichier plus loin, sans modification — StaticCodeAudit le signale à la ligne exacte où la requête s'exécute.

Comment ça se compare à Bandit ou Semgrep ?

Bandit et Semgrep sont les deux outils qui reviennent en premier quand une équipe Python cherche un scanner de sécurité gratuit. Les deux sont légitimes, et beaucoup d'équipes en utilisent déjà un — voici un comparatif honnête, pas un dénigrement.

Bandit

Gratuit, open source

Scanner basé sur l'AST, conçu spécifiquement pour les problèmes de sécurité Python (mots de passe en dur, shell=True, yaml.load non sécurisé). Mature et largement utilisé, mais limité à un seul fichier : pas de suivi de taint inter-fichiers, et les findings ne sont pas mappés CWE/ISO 27001/ASVS par défaut.

Semgrep (Community)

Gratuit, moteur open source

Moteur de pattern-matching couvrant de nombreux langages, dont Python, avec un large registre de règles ouvertes. Le tier gratuit couvre l'essentiel du quotidien ; le suivi de taint inter-fichiers, le reporting de conformité et certaines intégrations entreprise sont réservés aux tiers payants de Semgrep.

Comparatif complet StaticCodeAudit vs Semgrep →

Aucun des deux n'est remplacé par l'installation de StaticCodeAudit — si Bandit couvre déjà ce dont votre équipe a besoin, continuez à l'utiliser. Ce que StaticCodeAudit ajoute : des findings déjà mappés CWE/OWASP/ISO 27001/ASVS/NIST CSF (un finding prêt pour un dossier d'audit, pas juste un identifiant de règle), un suivi de taint inter-fichiers sur toute votre appli Flask/Django par défaut, et 7 autres langages couverts par le même binaire — pas de scanner séparé à configurer par langage. Beaucoup d'équipes utilisent les deux.

Auditez votre code

Auditez votre code Python pour les vulnérabilités OWASP Top 10, les misconfigurations spécifiques aux frameworks et les risques de dépendances — sans envoyer une seule ligne au cloud. Couvre Django, Flask, FastAPI, SQLAlchemy et la stdlib.

Télécharger le binaire démo Réserver une démo guidée