security-review

Examen du code de sécurité à la recherche de vulnérabilités. À utiliser quand on vous demande un « security review », « find vulnerabilities », « check for security issues », « audit security », « OWASP review », ou d'examiner le code pour les injections, XSS, authentification, autorisation, problèmes de cryptographie. Fournit un examen systématique avec un rapport basé sur le niveau de confiance.

npx skills add https://github.com/getsentry/skills --skill security-review

<!-- Matériel de référence basé sur la série OWASP Cheat Sheet (CC BY-SA 4.0) https://cheatsheetseries.owasp.org/ -->

Compétence en Audit de Sécurité

Identifier les vulnérabilités de sécurité exploitables dans le code. Signaler uniquement les résultats avec CONFIANCE ÉLEVÉE—des modèles vulnérables clairs avec des entrées contrôlées par l'attaquant.

Portée : Recherche vs. Signalement

DISTINCTION CRITIQUE :

  • Signaler : Uniquement le fichier spécifique, diff ou code fourni par l'utilisateur
  • Rechercher : L'ENSEMBLE de la base de code pour acquérir de la confiance avant de signaler

Avant de signaler un problème, vous DEVEZ rechercher dans la base de code pour comprendre :

  • D'où vient réellement cette entrée ? (Tracer le flux de données)
  • Y a-t-il une validation/sanitisation ailleurs ?
  • Comment cela est-il configuré ? (Vérifier les paramètres, fichiers de config, middleware)
  • Quelles protections du framework existent ?

NE PAS signaler les problèmes basés uniquement sur la correspondance de motifs. Enquêter d'abord, puis signaler uniquement ce dont vous êtes certain que c'est exploitable.

Niveaux de Confiance

Niveau Critères Action
ÉLEVÉE Motif vulnérable + entrée contrôlée par l'attaquant confirmée Signaler avec sévérité
MOYENNE Motif vulnérable, source d'entrée peu claire Noter comme « Nécessite vérification »
BASSE Théorique, bonne pratique, défense en profondeur Ne pas signaler

Ne Pas Signaler

Règles Générales

  • Fichiers de test (sauf examen explicite de la sécurité des tests)
  • Code mort, code commenté, chaînes de documentation
  • Motifs utilisant des constantes ou une configuration contrôlée par le serveur
  • Chemins de code nécessitant une authentification préalable pour être atteints (noter plutôt l'exigence d'auth)

Valeurs Contrôlées par le Serveur (NON Contrôlées par l'Attaquant)

Celles-ci sont configurées par les opérateurs, non contrôlées par les attaquants :

Source Exemple Pourquoi C'est Sûr
Django settings settings.API_URL, settings.ALLOWED_HOSTS Défini via config/env au déploiement
Variables d'environnement os.environ.get('DATABASE_URL') Configuration du déploiement
Fichiers de config config.yaml, app.config['KEY'] Fichiers côté serveur
Constantes du framework django.conf.settings.* Non modifiable par l'utilisateur
Valeurs en dur BASE_URL = "https://api.internal" Constantes au moment de la compilation

Exemple SSRF - PAS une vulnérabilité :

# SÛR : L'URL provient de Django settings (contrôlée par le serveur)
response = requests.get(f"{settings.SEER_AUTOFIX_URL}{path}")

Exemple SSRF - EST une vulnérabilité :

# VULNÉRABLE : L'URL provient de la requête (contrôlée par l'attaquant)
response = requests.get(request.GET.get('url'))

Motifs Atténués par le Framework

Vérifier les guides de langue avant de signaler. Faux positifs courants :

Motif Pourquoi C'est Généralement Sûr
Django {{ variable }} Auto-échappé par défaut
React {variable} Auto-échappé par défaut
Vue {{ variable }} Auto-échappé par défaut
User.objects.filter(id=input) ORM paramétre les requêtes
cursor.execute("...%s", (input,)) Requête paramétrée
innerHTML = "<b>Loading...</b>" Chaîne constante, pas d'entrée utilisateur

Signaler uniquement quand :

  • Django : {{ var|safe }}, {% autoescape off %}, mark_safe(user_input)
  • React : dangerouslySetInnerHTML={{__html: userInput}}
  • Vue : v-html="userInput"
  • ORM : .raw(), .extra(), RawSQL() avec interpolation de chaîne

Processus d'Audit

1. Détecter le Contexte

Quel type de code suis-je en train d'examiner ?

Type de Code Charger Ces Références
Points de terminaison API, routes authorization.md, authentication.md, injection.md
Frontend, modèles xss.md, csrf.md
Gestion de fichiers, uploads file-security.md
Crypto, secrets, tokens cryptography.md, data-protection.md
Sérialisation de données deserialization.md
Requêtes externes ssrf.md
Flux métier business-logic.md
GraphQL, conception REST api-security.md
Config, en-têtes, CORS misconfiguration.md
CI/CD, dépendances supply-chain.md
Gestion des erreurs error-handling.md
Audit, journalisation logging.md

2. Charger le Guide de Langue

Basé sur l'extension de fichier ou les imports :

Indicateurs Guide
.py, django, flask, fastapi languages/python.md
.js, .ts, express, react, vue, next languages/javascript.md
.go, go.mod languages/go.md
.rs, Cargo.toml languages/rust.md
.java, spring, @Controller languages/java.md

3. Charger le Guide d'Infrastructure (si applicable)

Type de Fichier Guide
Dockerfile, .dockerignore infrastructure/docker.md
Manifestes K8s, graphiques Helm infrastructure/kubernetes.md
.tf, Terraform infrastructure/terraform.md
GitHub Actions, .gitlab-ci.yml infrastructure/ci-cd.md
Configs AWS/GCP/Azure, IAM infrastructure/cloud.md

4. Rechercher Avant de Signaler

Pour chaque problème potentiel, rechercher dans la base de code pour acquérir de la confiance :

  • D'où vient réellement cette valeur ? Tracer le flux de données.
  • Est-elle configurée au déploiement (paramètres, variables env) ou provient-elle d'une entrée utilisateur ?
  • Y a-t-il une validation, une sanitisation ou une liste blanche ailleurs ?
  • Quelles protections du framework s'appliquent ?

Signaler uniquement les problèmes dont vous êtes SÛR après avoir compris le contexte plus large.

5. Vérifier l'Exploitabilité

Pour chaque résultat potentiel, confirmer :

L'entrée est-elle contrôlée par l'attaquant ?

Contrôlée par l'Attaquant (Enquêter) Contrôlée par le Serveur (Généralement Sûr)
request.GET, request.POST, request.args settings.X, app.config['X']
request.json, request.data, request.body os.environ.get('X')
request.headers (la plupart des en-têtes) Constantes en dur
request.cookies (non signées) URLs de services internes depuis la config
Segments de chemin URL : /users/<id>/ Contenu de la base de données depuis l'admin/système
Uploads de fichiers (contenu et noms) Données de session signées
Contenu de la base de données d'autres utilisateurs Paramètres du framework
Messages WebSocket

Le framework atténue-t-il cela ?

  • Vérifier le guide de langue pour l'auto-échappement, la paramétrisation
  • Vérifier les middleware/décorateurs qui sanitisent

Y a-t-il une validation en amont ?

  • Validation d'entrée avant ce code
  • Bibliothèques de sanitisation (DOMPurify, bleach, etc.)

6. Signaler Uniquement la Confiance Élevée

Ignorer les problèmes théoriques. Signaler uniquement ce dont vous avez confirmé l'exploitabilité après recherche.


Classification de Sévérité

Sévérité Impact Exemples
Critique Exploitation directe, impact grave, pas d'auth requise RCE, injection SQL sur données, contournement d'auth, secrets codés en dur
Élevée Exploitable avec conditions, impact significatif XSS stocké, SSRF vers métadonnées, IDOR sur données sensibles
Moyenne Conditions spécifiques requises, impact modéré XSS réfléchi, CSRF sur actions changeant l'état, traversée de répertoire
Basse Défense en profondeur, impact direct minimal En-têtes manquants, erreurs verboses, algorithmes faibles dans contexte non critique

Référence Rapide de Motifs

Toujours Signaler (Critique)

eval(user_input)           # N'importe quel langage
exec(user_input)           # N'importe quel langage
pickle.loads(user_data)    # Python
yaml.load(user_data)       # Python (pas safe_load)
unserialize($user_data)    # PHP
deserialize(user_data)     # Java ObjectInputStream
shell=True + user_input    # Python subprocess
child_process.exec(user)   # Node.js

Toujours Signaler (Élevé)

innerHTML = userInput              # DOM XSS
dangerouslySetInnerHTML={user}     # React XSS
v-html="userInput"                 # Vue XSS
f"SELECT * FROM x WHERE {user}"    # Injection SQL
`SELECT * FROM x WHERE ${user}`    # Injection SQL
os.system(f"cmd {user_input}")     # Injection de commande

Toujours Signaler (Secrets)

password = "hardcoded"
api_key = "sk-..."
AWS_SECRET_ACCESS_KEY = "..."
private_key = "-----BEGIN"

Vérifier le Contexte D'abord (DOIT Enquêter Avant de Signaler)

# SSRF - UNIQUEMENT si l'URL provient d'une entrée utilisateur, PAS de settings/config
requests.get(request.GET['url'])     # SIGNALER : URL contrôlée par l'utilisateur
requests.get(settings.API_URL)       # SÛR : Config contrôlée par le serveur
requests.get(f"{settings.BASE}/{x}") # VÉRIFIER : 'x' est-il une entrée utilisateur ?

# Traversée de répertoire - UNIQUEMENT si le chemin provient d'une entrée utilisateur
open(request.GET['file'])            # SIGNALER : Chemin contrôlé par l'utilisateur
open(settings.LOG_PATH)              # SÛR : Config contrôlée par le serveur
open(f"{BASE_DIR}/{filename}")       # VÉRIFIER : 'filename' est-il une entrée utilisateur ?

# Redirection ouverte - UNIQUEMENT si l'URL provient d'une entrée utilisateur
redirect(request.GET['next'])        # SIGNALER : Redirection contrôlée par l'utilisateur
redirect(settings.LOGIN_URL)         # SÛR : Config contrôlée par le serveur

# Crypto faible - UNIQUEMENT si utilisé à des fins de sécurité
hashlib.md5(file_content)            # SÛR : Checksums de fichiers, cache
hashlib.md5(password)                # SIGNALER : Hachage de mot de passe
random.random()                      # SÛR : Usages non-sécurité (UI, échantillonnage)
random.random() for token            # SIGNALER : Les tokens de sécurité ont besoin du module secrets

Format de Sortie

## Audit de Sécurité : [Nom du Fichier/Composant]

### Résumé
- **Résultats** : X (Y Critique, Z Élevée, ...)
- **Niveau de Risque** : Critique/Élevé/Moyen/Bas
- **Confiance** : Élevée/Mixte

### Résultats

#### [VULN-001] [Type de Vulnérabilité] (Sévérité)
- **Localisation** : `file.py:123`
- **Confiance** : Élevée
- **Problème** : [Ce qu'est la vulnérabilité]
- **Impact** : [Ce qu'un attaquant pourrait faire]
- **Preuve** :
  ```python
  [Extrait de code vulnérable]
  • Correction : [Comment remédier]

Nécessite Vérification

[VERIFY-001] [Problème Potentiel]

  • Localisation : file.py:456
  • Question : [Ce qui doit être vérifié]

Si aucune vulnérabilité n'est trouvée, indiquer : « Aucune vulnérabilité de confiance élevée identifiée. »


Fichiers de Référence

Vulnérabilités Principales (references/)

Fichier Couvre
injection.md SQL, NoSQL, commande OS, LDAP, injection de modèle
xss.md XSS réfléchi, stocké, basé sur DOM
authorization.md Autorisation, IDOR, escalade de privilèges
authentication.md Sessions, identifiants, stockage de mot de passe
cryptography.md Algorithmes, gestion des clés, aléa
deserialization.md Pickle, YAML, Java, désérialisation PHP
file-security.md Traversée de répertoire, uploads, XXE
ssrf.md Forgerie de requête côté serveur
csrf.md Contrefaçon de requête intersites
data-protection.md Exposition de secrets, PII, journalisation
api-security.md REST, GraphQL, affectation de masse
business-logic.md Conditions de course, contournement de flux
modern-threats.md Prototype pollution, injection LLM, WebSocket
misconfiguration.md En-têtes, CORS, mode debug, défauts
error-handling.md Fail-open, divulgation d'information
supply-chain.md Dépendances, sécurité de la build
logging.md Échecs d'audit, injection de journal

Guides de Langue (languages/)

  • python.md - Motifs Django, Flask, FastAPI
  • javascript.md - Node, Express, React, Vue, Next.js
  • go.md - Motifs de sécurité spécifiques à Go
  • rust.md - Blocs unsafe Rust, sécurité FFI
  • java.md - Motifs Spring, Java EE

Infrastructure (infrastructure/)

  • docker.md - Sécurité des conteneurs
  • kubernetes.md - K8s RBAC, secrets, politiques
  • terraform.md - Sécurité IaC
  • ci-cd.md - Sécurité du pipeline
  • cloud.md - Sécurité AWS/GCP/Azure