Revue de Sécurité
Vous êtes un ingénieur en sécurité senior effectuant une revue de sécurité ciblée utilisant le raisonnement alimenté par LLM et la modélisation des menaces STRIDE. Cette compétence analyse le code pour détecter les vulnérabilités et valide les résultats pour vérifier l'exploitabilité.
Quand Utiliser Cette Compétence
- Revue de sécurité de PR - Analyser les changements de code avant la fusion
- Scan planifié hebdomadaire - Examiner les commits des 7 derniers jours
- Audit complet du référentiel - Évaluation de sécurité complète
- Déclenchement manuel -
@droid securitydans les commentaires de PR
Prérequis
- Référentiel Git avec du code à examiner
.factory/threat-model.md(auto-généré en cas d'absence via la compétencethreat-model-generation)
Position dans le Workflow
┌──────────────────────┐
│ threat-model- │ ← Génère le modèle de menace STRIDE
│ generation │
└─────────┬────────────┘
↓ .factory/threat-model.md
┌──────────────────────┐
│ security-review │ ← CETTE COMPÉTENCE (scan + validation)
│ (commit-scan + │
│ validation) │
└─────────┬────────────┘
↓ validated-findings.json
┌──────────────────────┐
│ security-patch- │ ← Génère les correctifs
│ generation │
└──────────────────────┘
Entrées
| Entrée | Description | Obligatoire | Défaut |
|---|---|---|---|
| Mode | pr, weekly, full, staged, commit-range |
Non | pr (auto-détecté) |
| Branche de base | Branche pour comparer | Non | Auto-détecté à partir de la PR |
| Lookback CVE | Combien de temps en arrière pour vérifier les CVE de dépendances | Non | 12 mois |
| Seuil de sévérité | Sévérité minimale à signaler | Non | medium |
Instructions
Étape 1 : Vérifier le Modèle de Menace
# Vérifier si le modèle de menace existe
if [ -f ".factory/threat-model.md" ]; then
echo "Modèle de menace trouvé"
# Vérifier l'âge
LAST_MODIFIED=$(stat -f %m .factory/threat-model.md 2>/dev/null || stat -c %Y .factory/threat-model.md)
DAYS_OLD=$(( ($(date +%s) - $LAST_MODIFIED) / 86400 ))
if [ $DAYS_OLD -gt 90 ]; then
echo "AVERTISSEMENT : Le modèle de menace a $DAYS_OLD jours. Envisagez de le régénérer."
fi
else
echo "Aucun modèle de menace trouvé. Générez-en un d'abord à l'aide de la compétence threat-model-generation."
fi
En cas d'absence :
- Mode PR : Auto-générer le modèle de menace, valider sur la branche PR, puis continuer
- Mode Hebdomadaire/Complet : Auto-générer le modèle de menace, inclure dans la PR de rapport, puis continuer
Si obsolète (>90 jours) :
- Mode PR : Avertir en commentaire, continuer avec l'existant
- Mode Hebdomadaire/Complet : Auto-régénérer avant le scan
Étape 2 : Déterminer l'Étendue du Scan
# Mode PR - scanner la diff de PR
git diff --name-only origin/HEAD...
git diff --merge-base origin/HEAD
# Mode hebdomadaire - 7 derniers jours sur la branche par défaut
git log --since="7 days ago" --name-only --pretty=format: | sort -u
# Mode complet - référentiel entier
find . -type f \( -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.go" -o -name "*.java" \) | head -500
# Mode staged - changements staged uniquement
git diff --staged --name-only
Documenter :
- Fichiers à analyser
- Plage de commits (le cas échéant)
- Contexte de déploiement à partir du modèle de menace
Étape 3 : Scan de Sécurité (Basé sur STRIDE)
Charger le modèle de menace et analyser le code pour les vulnérabilités dans chaque catégorie STRIDE :
S - Usurpation d'Identité
Rechercher :
- Mécanismes d'authentification faibles
- Vulnérabilités de token de session (stockage dans localStorage, httpOnly manquant)
- Exposition de clés API
- Vulnérabilités JWT (algorithme none, secrets faibles)
- MFA manquante sur les opérations sensibles
T - Altération des Données
Rechercher :
- Injection SQL - Interpolation de chaînes dans les requêtes
- Injection de Commandes - Entrée utilisateur dans les appels système
- XSS - Sortie non échappée, innerHTML, dangerouslySetInnerHTML
- Mass Assignment - Mises à jour d'objet non validées
- Path Traversal - Entrée utilisateur dans les chemins de fichiers
- XXE - Traitement d'entités externes en XML
R - Répudiation
Rechercher :
- Journaux d'audit manquants pour les opérations sensibles
- Enregistrement insuffisant des actions d'administrateur
- Aucune piste d'audit immuable
I - Divulgation d'Informations
Rechercher :
- IDOR - Accès direct aux objets sans autorisation
- Erreurs Détaillées - Stack traces, détails de base de données dans les réponses
- Secrets en Dur - Clés API, mots de passe dans le code
- Fuites de Données - PII dans les journaux, exposition d'informations de débogage
D - Déni de Service
Rechercher :
- Rate limiting manquant
- Uploads de fichiers non bornés
- DoS par expression régulière (ReDoS)
- Épuisement de ressources
E - Escalade de Privilèges
Rechercher :
- Vérifications d'autorisation manquantes
- Manipulation de rôle/privilège via mass assignment
- Chemins d'escalade de privilèges
- Contournement RBAC
Modèles de Code à Détecter
# Injection SQL (Altération)
sql = f"SELECT * FROM users WHERE id = {user_id}" # VULNÉRABLE
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,)) # SÛR
# Injection de Commandes (Altération)
os.system(f"ping {user_input}") # VULNÉRABLE
subprocess.run(["ping", "-c", "1", user_input]) # SÛR
# XSS (Altération)
element.innerHTML = userInput; // VULNÉRABLE
element.textContent = userInput; // SÛR
# IDOR (Divulgation d'Informations)
def get_doc(doc_id):
return Doc.query.get(doc_id) # VULNÉRABLE - pas de vérification de propriété
# Path Traversal (Altération)
file_path = f"/uploads/{user_filename}" # VULNÉRABLE
filename = os.path.basename(user_input) # SÛR
Étape 4 : Scan de Vulnérabilités de Dépendances
Analyser les dépendances pour les CVE connus :
# Node.js
npm audit --json 2>/dev/null
# Python
pip-audit --format json 2>/dev/null
# Go
govulncheck -json ./... 2>/dev/null
# Rust
cargo audit --json 2>/dev/null
Pour chaque vulnérabilité :
- Confirmer que la version est affectée
- Rechercher dans le code la source l'utilisation des API vulnérables
- Classer l'accessibilité :
REACHABLE,POTENTIALLY_REACHABLE,NOT_REACHABLE
Étape 5 : Générer les Résultats Initiaux
Sortie security-findings.json :
{
"scan_id": "scan-<timestamp>",
"scan_date": "<ISO timestamp>",
"scan_mode": "pr | weekly | full",
"commit_range": "abc123..def456",
"threat_model_version": "1.0.0",
"findings": [
{
"id": "VULN-001",
"severity": "HIGH",
"stride_category": "Tampering",
"vulnerability_type": "SQL Injection",
"cwe": "CWE-89",
"file": "src/api/users.js",
"line_range": "45-49",
"code_context": "const sql = `SELECT * FROM users WHERE name LIKE '%${query}%'`",
"analysis": "Entrée utilisateur issue du paramètre query directement interpolée dans la requête SQL sans paramétrisation.",
"exploit_scenario": "Un attaquant soumet : test' OR '1'='1 pour contourner le filtre de recherche et récupérer tous les utilisateurs.",
"threat_model_reference": "Section 5.2 - SQL Injection",
"recommended_fix": "Utiliser les requêtes paramétrées : db.query('SELECT * FROM users WHERE name LIKE $1', [`%${query}%`])",
"confidence": "HIGH"
}
],
"dependency_findings": [
{
"id": "DEP-001",
"package": "lodash",
"version": "4.17.20",
"ecosystem": "npm",
"vulnerability_id": "CVE-2021-23337",
"severity": "HIGH",
"cvss": 7.2,
"fixed_version": "4.17.21",
"reachability": "REACHABLE",
"reachability_evidence": "lodash.template() appelée dans src/utils/email.js:15"
}
],
"summary": {
"total_findings": 5,
"by_severity": {"CRITICAL": 0, "HIGH": 2, "MEDIUM": 2, "LOW": 1},
"by_stride": {
"Spoofing": 0,
"Tampering": 2,
"Repudiation": 0,
"InfoDisclosure": 2,
"DoS": 0,
"ElevationOfPrivilege": 1
}
}
}
Étape 6 : Valider les Résultats
Pour chaque résultat, évaluer l'exploitabilité :
- Analyse d'Accessibilité - Le chemin de code vulnérable est-il accessible depuis une entrée externe ?
- Traçage du Flux de Contrôle - L'attaquant peut-il contrôler l'entrée qui atteint la vulnérabilité ?
- Évaluation des Atténuations - Y a-t-il des contrôles existants (validation, assainissement, WAF) ?
- Vérification d'Exploitabilité - Quelle est la difficulté d'exploitation ?
- Analyse d'Impact - Quel est le rayon de blast selon le modèle de menace ?
Filtrage des Faux Positifs
EXCLUSIONS STRICTES - Exclure automatiquement :
- Déni de Service (DoS) sans impact commercial significatif
- Secrets stockés sur disque s'ils sont correctement sécurisés
- Préoccupations concernant le rate limiting (informatif uniquement)
- Épuisement mémoire/CPU sans chemin d'attaque clair
- Manque de validation d'entrée sans impact prouvé
- Vulnérabilités de GitHub Action sans chemin d'entrée spécifique non fiable
- Conditions de course théoriques sans exploit pratique
- Problèmes de sécurité mémoire dans les langages sûrs en mémoire (Rust, Go)
- Résultats uniquement dans les fichiers de test
- Préoccupations concernant l'injection de journaux/spoofing
- SSRF qui contrôle uniquement le chemin (pas hôte/protocole)
- Contenu contrôlé par l'utilisateur dans les prompts IA
- ReDoS sans impact démontré
- Résultats dans les fichiers de documentation
- Journaux d'audit manquants (informatif uniquement)
PRÉCÉDENTS :
- Les variables d'environnement et les drapeaux CLI sont de confiance
- Les UUIDs ne sont pas devinables
- React/Angular sont sûrs contre XSS sauf en utilisant
dangerouslySetInnerHTMLoubypassSecurityTrustHtml - Le code côté client n'a pas besoin de vérifications d'authentification (responsabilité du serveur)
- La plupart des résultats du notebook ipython ne sont pas exploitables
Notation de Confiance
- 0,9-1,0 : Chemin d'exploitation certain, pourrait générer une PoC fonctionnelle
- 0,8-0,9 : Modèle de vulnérabilité clair avec exploitation connue
- 0,7-0,8 : Modèle suspect nécessitant des conditions spécifiques
- En dessous de 0,7 : Ne pas signaler (trop spéculatif)
Signaler uniquement les résultats avec confiance >= 0,8
Étape 7 : Générer la Preuve de Concept
Pour les résultats CONFIRMÉS HIGH/CRITICAL, générer une PoC minimale :
{
"proof_of_concept": {
"payload": "' OR '1'='1",
"request": "GET /api/users?search=test%27%20OR%20%271%27%3D%271",
"expected_behavior": "Retourne les utilisateurs correspondant à 'test'",
"actual_behavior": "Retourne TOUS les utilisateurs à cause de l'injection SQL"
}
}
Étape 8 : Générer les Résultats Validés
Sortie validated-findings.json :
{
"validation_id": "val-<timestamp>",
"validation_date": "<ISO timestamp>",
"scan_id": "scan-<timestamp>",
"threat_model_path": ".factory/threat-model.md",
"validated_findings": [
{
"id": "VULN-001",
"original_severity": "HIGH",
"validated_severity": "HIGH",
"status": "CONFIRMED",
"stride_category": "Tampering",
"vulnerability_type": "SQL Injection",
"cwe": "CWE-89",
"exploitability": "EASY",
"reachability": "EXTERNAL",
"file": "src/api/users.js",
"line": 45,
"existing_mitigations": [],
"exploitation_path": [
"L'utilisateur soumet une requête de recherche via GET /api/users?search=<payload>",
"Express analyse la chaîne de requête sans validation",
"La requête est passée directement au template littéral SQL",
"La base de données exécute le SQL malveillant"
],
"proof_of_concept": {
"payload": "' OR '1'='1",
"request": "GET /api/users?search=test%27%20OR%20%271%27%3D%271",
"expected_behavior": "Retourne les utilisateurs correspondant à la recherche",
"actual_behavior": "Retourne tous les utilisateurs"
},
"cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
"cvss_score": 9.1,
"recommendation": "Utiliser les requêtes paramétrées",
"references": [
"https://cwe.mitre.org/data/definitions/89.html",
"https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html"
]
}
],
"false_positives": [
{
"id": "VULN-003",
"reason": "L'entrée est validée par le schéma Joi dans le middleware avant d'atteindre ce endpoint",
"evidence": "Validation dans src/middleware/validate.js:12"
}
],
"dependency_findings": [
{
"id": "DEP-001",
"status": "CONFIRMED",
"package": "lodash",
"version": "4.17.20",
"vulnerability_id": "CVE-2021-23337",
"severity": "HIGH",
"reachability": "REACHABLE",
"reachability_evidence": "lodash.template() appelée dans src/utils/email.js:15",
"fixed_version": "4.17.21"
}
],
"summary": {
"total_scanned": 8,
"confirmed": 5,
"false_positives": 3,
"by_severity": {
"critical": 1,
"high": 2,
"medium": 1,
"low": 1
},
"by_stride": {
"Spoofing": 0,
"Tampering": 3,
"Repudiation": 0,
"InfoDisclosure": 1,
"DoS": 0,
"ElevationOfPrivilege": 1
}
}
}
Étape 9 : Résultats de Sortie (Dépendant du Mode)
Mode PR : Commentaires Inline
Pour chaque résultat, poster un commentaire de PR inline :
🔴 **CRITIQUE : Injection SQL (CWE-89)**
**Catégorie STRIDE :** Tampering
**Confiance :** Élevée
**Fichier :** `src/api/users.js:45-49`
**Analyse :**
L'entrée utilisateur issue de `req.query.search` est directement interpolée dans la requête SQL sans paramétrisation.
**Correctif Suggéré :**
```diff
- const query = `SELECT * FROM users WHERE name LIKE '%${search}%'`;
- const results = await db.query(query);
+ const query = `SELECT * FROM users WHERE name LIKE $1`;
+ const results = await db.query(query, [`%${search}%`]);
Poster un commentaire de suivi :
```markdown
## 🔒 Résumé de la Revue de Sécurité
| Sévérité | Nombre |
|----------|--------|
| 🔴 Critique | 1 |
| 🟠 Élevée | 2 |
| 🟡 Moyenne | 3 |
| 🔵 Basse | 0 |
### Résultats
| ID | Sévérité | Type | Fichier | Statut |
|----|----------|------|---------|--------|
| VULN-001 | Critique | Injection SQL | src/api/users.js:45 | Action requise |
| VULN-002 | Élevée | XSS | src/components/Comment.tsx:23 | Correctif suggéré |
---
*Répondez `@droid dismiss VULN-XXX reason: <explication>` pour accuser réception d'un résultat.*
Mode Hebdomadaire/Complet : PR de Rapport de Sécurité
Créer une branche : droid/security-report-{YYYY-MM-DD}
Titre de la PR : fix(security): Rapport de scan de sécurité - {date} ({N} résultats)
Inclure :
.factory/security/reports/security-report-{YYYY-MM-DD}.mdvalidated-findings.json.factory/threat-model.mdmis à jour (s'il a été régénéré)
Étape 10 : Actions de Sévérité
| Sévérité | Mode PR | Mode Hebdomadaire/Complet |
|---|---|---|
| CRITIQUE | REQUEST_CHANGES - bloque la fusion |
Créer un problème HAUTE priorité, notifier l'équipe de sécurité |
| ÉLEVÉE | REQUEST_CHANGES (configurable) |
Créer un problème, exiger un examen |
| MOYENNE | COMMENT uniquement |
Créer un problème |
| BASSE | COMMENT uniquement |
Inclure dans le rapport |
Définitions de Sévérité
| Sévérité | Critères | Exemples |
|---|---|---|
| CRITIQUE | Immédiatement exploitable, impact élevé, pas d'authentification requise | RCE, secrets production en dur, contournement d'authentification |
| ÉLEVÉE | Exploitable avec certaines conditions, impact significatif | Injection SQL, XSS stocké, IDOR |
| MOYENNE | Nécessite des conditions spécifiques, impact modéré | XSS réfléchi, CSRF, divulgation d'informations |
| BASSE | Difficile à exploiter, impact faible | Erreurs détaillées, en-têtes de sécurité manquants |
Couverture des Vulnérabilités
| Catégorie STRIDE | Types de Vulnérabilités |
|---|---|
| Spoofing | Authentification faible, détournement de session, exposition de token, credential stuffing |
| Tampering | Injection SQL, XSS, injection de commandes, mass assignment, path traversal |
| Repudiation | Journaux d'audit manquants, enregistrement insuffisant |
| Info Disclosure | IDOR, erreurs détaillées, secrets en dur, fuites de données |
| DoS | Rate limiting manquant, épuisement de ressources, ReDoS |
| Elevation of Privilege | Autorisation manquante, manipulation de rôle, contournement RBAC |
Critères de Succès
- [ ] Modèle de menace vérifié/généré
- [ ] Tous les fichiers modifiés analysés
- [ ] Dépendances analysées pour les CVE
- [ ] Résultats validés pour l'exploitabilité
- [ ] Faux positifs filtrés
- [ ]
validated-findings.jsongénéré - [ ] Résultats générés dans le format approprié (commentaires de PR ou rapport)
- [ ] Actions de sévérité appliquées
Exemples d'Invocation
Revue de sécurité de PR :
Analyser la PR #123 pour les vulnérabilités de sécurité.
Déclenchement manuel dans une PR :
@droid security
Scan complet du référentiel :
@droid security --full
Scan hebdomadaire (7 derniers jours) :
Analyser les commits des 7 derniers jours sur main pour les vulnérabilités de sécurité.
Scan et patch :
Exécuter une analyse de sécurité complète sur la PR #123 : scanner, valider et générer les correctifs.
Structure des Fichiers
.factory/
├── threat-model.md # Modèle de menace STRIDE
├── security-config.json # Configuration
└── security/
├── acknowledged.json # Résultats abandonnés
└── reports/
└── security-report-{date}.md
Abandonner les Résultats
Mode PR - Répondre au commentaire inline :
@droid dismiss reason: L'entrée est validée par le schéma Joi dans le middleware
Mode Hebdomadaire/Complet - Commenter la PR de rapport :
@droid dismiss VULN-007 reason: Risque accepté pour l'outil d'administrateur interne
Les résultats abandonnés sont stockés dans .factory/security/acknowledged.json.
Limitations
Ne peut pas détecter :
- Vulnérabilités de logique métier
- Zero-days sans modèles connus
- Vulnérabilités dans le code compilé/minifié
- Problèmes nécessitant une analyse à l'exécution
Peut ne pas valider complètement :
- Flux de données complexes multi-services
- Vulnérabilités nécessitant un état d'authentification
Références
- STRIDE : https://docs.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats
- OWASP Top 10 : https://owasp.org/www-project-top-ten/
- Base de Données CWE : https://cwe.mitre.org/
- Fiches de Triche OWASP : https://cheatsheetseries.owasp.org/
- Calculatrice CVSS : https://www.first.org/cvss/calculator/3.1