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.
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 — 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 — 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 — shell=True avec entrée utilisateur
import subprocess
def ping(host):
return subprocess.run(f"ping -c 1 {host}", shell=True)
# 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 — yaml.load sans SafeLoader
import yaml
def load_config(blob):
return yaml.load(blob) # Loader complet = RCE
# 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 (
subprocessavecshell=True,os.system,os.popen) - Désérialisation non sécurisée (
pickle,yaml.load,marshal,shelve) - SSRF via
requests,urllib,aiohttpsur 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,lxmlsans resolver désactivé) - Path traversal (
os.path.joinavec entrée utilisateur,open()sans ancrage racine) - Cookies non sécurisés (flags Flask/Django
Secure/HttpOnly/SameSitemanquants) - CSRF exempté (
@csrf_exempt, Flask sansflask-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)
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.
CVE Test Suite, par framework — 2 frameworks sur 3 à F1 = 100 %
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.
@app.route("/orders")
def find_order():
order_id = request.args.get("id")
return jsonify(get_order(order_id))
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 sourceScanner 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 sourceMoteur 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