Référence DSL .sca — StaticCodeAudit par CodeFixture
Ce document décrit la syntaxe complète des fichiers de règles .sca. Chaque fichier définit une règle de détection autonome.
1. Structure d'une règle
Un fichier .sca contient une seule règle. Structure minimale :
rule mon_id_de_regle
language python
severity HIGH
match
pattern mon_pattern_regex
end
risk
en: English risk description
fr: Description du risque en français
end
solution
en: English fix
fr: Correction en français
end
end
rule_id doit être en minuscules avec underscores uniquement : [a-z0-9_]+2. Mots-clés de la règle
| Mot-clé | Valeurs | Obligatoire | Description |
|---|---|---|---|
language | python, javascript, java, csharp, php, html, yaml, dockerfile | requis | Langage du code analysé |
severity | CRITICAL, HIGH, MEDIUM, LOW, INFO | requis | Sévérité du finding |
category | security, arch, ui, ux, maintenance, cicd | optionnel | Catégorie (défaut : security) |
confidence | 0 à 100 | optionnel | Confiance en % (défaut : 80) |
3. Bloc match (détection par pattern)
Le bloc match définit les patterns à détecter dans le code. Répétable (plusieurs blocs = OU).
3.1 Mots-clés du bloc match
| Mot-clé | Type | Description |
|---|---|---|
pattern | Regex | Expression régulière à chercher |
text | Texte brut | Texte échappé automatiquement. * = joker (n'importe quoi) |
with | Regex | Le contexte doit aussi contenir ce pattern |
with-text | Texte brut | Comme with mais échappé automatiquement |
pattern-not | Regex | Le contexte ne doit pas contenir ce pattern |
text-not | Texte brut | Comme pattern-not mais échappé |
scope | Valeur | Portée de la recherche (voir ci-dessous) |
3.2 Scopes
| Scope | Comportement du pattern | Comportement du pattern-not |
|---|---|---|
line | Vérifié ligne par ligne | Vérifié sur la même ligne |
context-N | Vérifié sur des fenêtres de N lignes | Vérifié sur le bloc de N lignes entier |
file | Vérifié sur le fichier entier | Vérifié sur le fichier entier |
3.3 text vs pattern
text — pour tous les développeurs. L'outil échappe automatiquement les caractères spéciaux. Le * signifie "n'importe quoi".
match
text .execute(
with-text f"*"
scope context-4
end
pattern — pour les experts regex. Le pattern est utilisé tel quel.
match
pattern \.execute\s*\(.*f["']
scope context-4
end
Les deux exemples ci-dessus détectent le même code.
4. Bloc requires (conditions fichier)
Le bloc requires définit des conditions sur le fichier. Si utilisé seul (sans match), le finding est au niveau du fichier (ligne 1). Si combiné avec match, il sert de pré-filtre.
| Mot-clé | Logique | Description | Exemple |
|---|---|---|---|
has | TOUS doivent matcher | Le contenu du fichier doit contenir ce pattern | has @app\.route |
not_has | AUCUN ne doit matcher | Le contenu du fichier ne doit PAS contenir ce pattern | not_has logging |
min_lines | ≥ N | Le fichier doit avoir au moins N lignes | min_lines 500 |
path_contains | AU MOINS UN doit matcher | Le chemin du fichier doit contenir ce segment | path_contains vendor/ |
not_path_has_file | AUCUN ne doit exister | Le répertoire du fichier ne doit PAS contenir ce fichier | not_path_has_file LICENSE |
has, not_has, path_contains et not_path_has_file sont répétables (plusieurs lignes = plusieurs conditions).Exemples
# Fichier Flask sans logging
requires
has @app\.route
not_has import\s+logging
end
# Fichier trop long
requires
min_lines 500
end
# Code vendor sans LICENSE
requires
path_contains vendor/
not_path_has_file LICENSE
not_path_has_file LICENSE.md
end
5. Analyse taint (source → sink)
L'analyse taint trace le flux de données depuis des sources (entrées utilisateur) vers des sinks (fonctions dangereuses), sauf si un sanitizer intervient.
| Mot-clé | Syntaxe | Description |
|---|---|---|
source | source <regex> kind=<type> | Origine des données non fiables |
sink | sink <regex> | Fonction dangereuse recevant les données |
sanitizer | sanitizer <regex> | Fonction qui neutralise les données |
Types de sources (kind=) : http, stdin, cli, env, file, network
rule taint_sqli
language python
severity HIGH
source request\.args\.get\( kind=http
source request\.form\[ kind=http
source input\s*\( kind=stdin
sink \.execute\s*\(
sink \.executemany\s*\(
sanitizer \bint\s*\(
sanitizer psycopg2\.sql\.SQL
end
6. Blocs i18n (risk, solution, message)
Les blocs risk, solution, benefit et message supportent la traduction en 4 langues :
risk
en: User input in SQL query allows injection.
fr: Entrée utilisateur dans la requête SQL permet l'injection.
es: Entrada de usuario en consulta SQL permite inyección.
de: Benutzereingabe in SQL-Abfrage ermöglicht Injection.
end
en, fr, es, de. Le rapport utilise la langue configurée dans --lang.7. Bloc metadata (CWE, CVE, OWASP, ISO, WCAG)
metadata
cwe CWE-89
cwe CWE-90
cve CVE-2021-44228
owasp A03:2021
iso27001 A.8.28 A.8.25
asvs 5.3.4
wcag 1.1.1
end
| Clé | Format | Description |
|---|---|---|
cwe | CWE-NNN (multi) | Common Weakness Enumeration. Plusieurs valeurs via lignes répétées ou tokens séparés par des espaces. |
cve | CVE-YYYY-NNNN (multi) | CVE spécifique pour laquelle la règle a été créée. Affichée comme lien clickable vers la NVD. |
owasp | ANN:YYYY | OWASP Top 10 |
iso27001 | A.N.NN (multi) | ISO/IEC 27001:2022 Annex A |
asvs | N.N.N (multi) | OWASP ASVS |
wcag | N.N.N (multi) | Critère W3C WCAG 2.1 (utilisé par les règles d'accessibilité au lieu de CWE). |
Toutes les clés multi-valeurs (cwe, cve,
iso27001, asvs, wcag) acceptent
plusieurs tokens sur la même ligne (cwe CWE-89 CWE-90)
ou des lignes répétées — les valeurs sont accumulées.
La classification metadata est propagée à tous les exports :
HTML (liens clickables), JSON (objet finding.compliance)
et SARIF (rule.properties.tags).
8. Modes d'exécution
Le mode est inféré automatiquement depuis les blocs présents :
| Blocs présents | Mode inféré |
|---|---|
match (pattern/text) | regex |
requires seul (has/not_has/min_lines) | file_contains |
match + requires | regex avec pré-filtre fichier |
source + sink | taint |
source + sink + match | regex+taint |
hook | python_hook (règles custom avancées) |
mode explicitement — l'inférence automatique est recommandée.9. Exemples complets
9.1 Détection simple (texte brut)
rule console_log_residual
language javascript
severity LOW
category ux
match
text console.log(
end
risk
en: console.log() calls left in production code.
fr: Appels console.log() laissés en production.
end
solution
en: Remove console.log() or use a logging system.
fr: Supprimer les console.log() ou utiliser un système de logging.
end
end
9.2 Pattern avec exclusion (context)
rule insecure_cookie
language python
severity MEDIUM
match
pattern \.set_cookie\s*\(
pattern-not (?:httponly\s*=\s*True|secure\s*=\s*True)
scope context-4
end
risk
en: Cookie without HttpOnly/Secure flags.
fr: Cookie sans flags HttpOnly/Secure.
end
solution
en: Add httponly=True, secure=True, samesite="Lax".
fr: Ajouter httponly=True, secure=True, samesite="Lax".
end
end
9.3 Condition fichier seule
rule file_too_long
language python
severity LOW
category arch
requires
min_lines 500
end
risk
en: Very long files are difficult to maintain.
fr: Les fichiers très longs sont difficiles à maintenir.
end
solution
en: Split into smaller, focused modules.
fr: Découper en modules plus petits et focalisés.
end
end
9.4 Combo match + requires
rule missing_auth_decorator
language python
severity MEDIUM
match
pattern @app\.route\s*\(\s*[\"'](?:/admin|/api/delete)
pattern-not @login_required
scope context-4
end
risk
en: Admin route without authentication decorator.
fr: Route admin sans décorateur d'authentification.
end
solution
en: Add @login_required on all sensitive routes.
fr: Ajouter @login_required sur toutes les routes sensibles.
end
end
9.5 Analyse taint (injection SQL)
rule taint_sqli
language python
severity HIGH
confidence 90
source request\.args\.get\( kind=http
source request\.form\[ kind=http
sink \.execute\s*\(
sink \.executemany\s*\(
sanitizer psycopg2\.sql\.SQL
sanitizer \bint\s*\(
risk
en: Tainted data flows into SQL query without parameterization.
fr: Données non fiables atteignent une requête SQL sans paramétrage.
end
solution
en: Use parameterized queries with placeholders (%s, ?).
fr: Utilisez des requêtes paramétrées avec placeholders (%s, ?).
end
metadata
cwe CWE-89
owasp A03:2021
end
end
9.6 Vérification de gouvernance vendor
rule unreviewed_vendor_code
language python
severity LOW
category maintenance
requires
path_contains vendor/
path_contains third-party/
not_path_has_file LICENSE
not_path_has_file NOTICE
end
risk
en: Vendor code without LICENSE file.
fr: Code tiers sans fichier LICENSE.
end
solution
en: Add LICENSE file to vendor directories.
fr: Ajouter un fichier LICENSE aux répertoires vendor.
end
end
10. Glossaire
| Terme | Définition |
|---|---|
| DSL | Domain-Specific Language — langage dédié à la définition de règles d'audit |
| Finding | Problème détecté par une règle (vulnérabilité, défaut d'architecture, etc.) |
| Pattern | Expression régulière ou texte brut cherché dans le code |
| Scope | Portée de la recherche : ligne, bloc de N lignes, ou fichier entier |
| Source | Entrée de données non fiables (requête HTTP, entrée clavier, etc.) |
| Sink | Fonction dangereuse où les données non fiables ne doivent pas arriver sans validation |
| Sanitizer | Fonction qui neutralise les données dangereuses (échappement, validation, conversion) |
| Taint | Marquage des données comme "contaminées" pour suivre leur propagation dans le code |
| CWE | Common Weakness Enumeration — catalogue de faiblesses logicielles |
| OWASP | Open Web Application Security Project — Top 10 des risques de sécurité web |
| ASVS | Application Security Verification Standard — niveaux de vérification sécurité |
| ISO 27001 | Norme internationale de gestion de la sécurité de l'information |
| SAST | Static Application Security Testing — analyse de sécurité sans exécuter le code |
StaticCodeAudit — CodeFixture | Documentation DSL v1.0