security-review

Par factory-ai · factory-plugins

Analysez les modifications de code à la recherche de vulnérabilités de sécurité en utilisant la modélisation des menaces STRIDE, validez les résultats pour leur exploitabilité et produisez des résultats structurés pour la génération de correctifs en aval. Prend en charge la revue de PR, les scans planifiés et les audits complets de dépôt.

npx skills add https://github.com/factory-ai/factory-plugins --skill security-review

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 security dans 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étence threat-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é :

  1. Confirmer que la version est affectée
  2. Rechercher dans le code la source l'utilisation des API vulnérables
  3. 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é :

  1. Analyse d'Accessibilité - Le chemin de code vulnérable est-il accessible depuis une entrée externe ?
  2. Traçage du Flux de Contrôle - L'attaquant peut-il contrôler l'entrée qui atteint la vulnérabilité ?
  3. Évaluation des Atténuations - Y a-t-il des contrôles existants (validation, assainissement, WAF) ?
  4. Vérification d'Exploitabilité - Quelle est la difficulté d'exploitation ?
  5. Analyse d'Impact - Quel est le rayon de blast selon le modèle de menace ?

Filtrage des Faux Positifs

EXCLUSIONS STRICTES - Exclure automatiquement :

  1. Déni de Service (DoS) sans impact commercial significatif
  2. Secrets stockés sur disque s'ils sont correctement sécurisés
  3. Préoccupations concernant le rate limiting (informatif uniquement)
  4. Épuisement mémoire/CPU sans chemin d'attaque clair
  5. Manque de validation d'entrée sans impact prouvé
  6. Vulnérabilités de GitHub Action sans chemin d'entrée spécifique non fiable
  7. Conditions de course théoriques sans exploit pratique
  8. Problèmes de sécurité mémoire dans les langages sûrs en mémoire (Rust, Go)
  9. Résultats uniquement dans les fichiers de test
  10. Préoccupations concernant l'injection de journaux/spoofing
  11. SSRF qui contrôle uniquement le chemin (pas hôte/protocole)
  12. Contenu contrôlé par l'utilisateur dans les prompts IA
  13. ReDoS sans impact démontré
  14. Résultats dans les fichiers de documentation
  15. 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 dangerouslySetInnerHTML ou bypassSecurityTrustHtml
  • 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}%`]);

CWE-89: Injection SQL


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}.md
  • validated-findings.json
  • .factory/threat-model.md mis à 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.json gé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

Skills similaires