Audit Auth — Audit de sécurité d'authentification
Réalise un audit de sécurité complet du système d'authentification d'une application. Analyse le backend, le frontend et l'infrastructure pour identifier les vulnérabilités, les mauvaises pratiques et les améliorations possibles. Produit un rapport structuré avec sévérité et correctifs.
Variables
CHEMIN_PROJET: $ARGUMENTS
Instructions
- Si aucun
CHEMIN_PROJET n'est fourni, STOP et demande à l'utilisateur de le fournir (AskUserQuestion).
- Utilise le mode team : crée une équipe avec les agents décrits ci-dessous pour paralléliser l'audit.
- Chaque agent produit ses findings. Le chef d'équipe compile le rapport final.
- Le rapport final doit être sauvegardé dans
CHEMIN_PROJET/audit-auth-report.md.
Équipe d'audit
Crée une équipe via TeamCreate avec les membres suivants. Chaque agent est un builder ou general-purpose.
Agent 1 : backend-auditor
Subagent type : general-purpose
Mission : Auditer tout le code backend lié à l'authentification.
Checklist à vérifier :
JWT Configuration
- Algorithme (HS256 minimum, RS256 préféré pour microservices)
- Longueur de la clé secrète (>= 32 chars pour HS256, >= 2048 bits pour RS256)
- TTL des tokens (access <= 30 min, refresh <= 7 jours)
- Validation du type de token (access vs refresh vs totp_pending)
- Présence du claim
exp vérifié automatiquement
- Présence du claim
sub avec UUID valide
Stockage des tokens
- Cookies HttpOnly (pas localStorage)
- Attributs :
secure=True, samesite=lax|strict, paths scopés
- Refresh token avec path restreint (
/api/auth pas /api)
Hachage des mots de passe
- Algorithme : Argon2id (recommandé) ou bcrypt (acceptable)
- Pas de MD5, SHA1, SHA256 nu, ou stockage en clair
passlib déprécié — vérifier la lib utilisée
Rate limiting
- Présent sur login, register, refresh, reset password, magic link
- Limites raisonnables (5-10/min par IP)
- Handler HTTP 429 configuré
Protection mass assignment
_ALLOWED_FIELDS ou extra="forbid" sur chaque endpoint d'update
- Pas de
setattr() sans whitelist
CORS
- Pas de
allow_origins=["*"] avec credentials
- Méthodes et headers explicites (pas
["*"])
Injection SQL
- Utilisation d'un ORM (SQLModel/SQLAlchemy)
- Échappement des wildcards LIKE (
%, _)
- Pas de requêtes SQL brutes avec f-strings
Gestion des erreurs & anti-énumération
- Messages génériques vers le client (pas de stack traces, pas de détails d'API externes)
- Énumération d'utilisateurs : le login doit retourner un message identique que l'email existe ou non (ex: "Identifiants invalides") — jamais "Email inconnu" vs "Mot de passe incorrect"
- Même principe sur reset password / magic link : "Si cet email existe, un lien a été envoyé"
- Vérifier que le timing de réponse est constant (pas de shortcut si l'email n'existe pas)
Logs d'authentification
- Les tentatives de login échouées sont-elles loggées ? (avec IP, email, timestamp)
- Les mots de passe ne sont PAS loggés (grep
password dans les appels logger/print)
- Les tokens JWT ne sont PAS loggés en clair
- Les événements de sécurité (changement MDP, activation 2FA, logout) sont-ils loggés ?
Sessions concurrentes
- Existe-t-il une limite sur le nombre de sessions actives par utilisateur ?
- Si refresh tokens sont stockés en BD : combien peut-on en avoir simultanément ?
- Pour les apps métier sensibles : envisager une limite (ex: 5 sessions max) avec invalidation de la plus ancienne
Refresh token
- Rotation à chaque usage
- Révocation possible (blacklist ou token family)
- Vérification user en BD à chaque refresh
2FA / TOTP
- Secret stocké (idéalement chiffré)
valid_window raisonnable (1-2)
- Rate limiting sur verify-totp
Logout
- Suppression des cookies côté serveur
- Idéalement : invalidation côté serveur (blacklist)
Dépendances Python vulnérables
- Lancer
pip-audit ou uv run pip-audit (si disponible)
- Vérifier les versions de PyJWT, cryptography, bcrypt/argon2-cffi
Agent 2 : frontend-auditor
Subagent type : general-purpose
Mission : Auditer tout le code frontend lié à l'authentification.
Checklist à vérifier :
Stockage des tokens
- Aucun token dans localStorage, sessionStorage, ou variable JS
credentials: "include" sur tous les fetch/axios
- Pas de header
Authorization: Bearer xxx construit manuellement depuis le client
Protection XSS
- Pas de
dangerouslySetInnerHTML sans DOMPurify
- Pas d'
eval(), new Function(), ou innerHTML avec données dynamiques
- CSP header configuré
Validation des URLs
isValidDownloadUrl() ou équivalent avant window.open()
- Blocage des protocoles
javascript:, data:, file://
encodeURIComponent() sur tous les IDs dans les URLs API
Route guards
- Vérification auth sur chaque route protégée
- Redirection vers /login si non authentifié
- Pas de contenu flash avant redirection
Refresh flow
- Interception des 401 → refresh → retry
- Déduplication des appels refresh parallèles
- Redirection /login si refresh échoue + appel logout serveur
Vérification HTTPS
- Warning ou blocage si protocole != https en production
Cache React Query / state
queryClient.clear() au logout
- Pas de données sensibles persistées dans le state après logout
Dépendances JS vulnérables
- Lancer
pnpm audit ou npm audit
- Vérifier les versions de dompurify, react, etc.
Agent 3 : infra-auditor
Subagent type : general-purpose
Mission : Auditer la configuration infrastructure et les headers de sécurité.
Checklist à vérifier :
Headers HTTP
Strict-Transport-Security (HSTS) avec max-age >= 1 an
Content-Security-Policy configuré (pas unsafe-inline sauf nécessité documentée)
X-Content-Type-Options: nosniff
X-Frame-Options: DENY ou SAMEORIGIN
Permissions-Policy restrictif
Referrer-Policy: strict-origin-when-cross-origin
- Pas de header
Server exposé (version du serveur)
Docker
- Conteneurs non-root (
USER appuser)
- Images pinnées sur des versions exactes (pas
latest)
- Ports non-privilégiés pour nginx/frontends
- Limites CPU/mémoire définies
- Pas de secrets dans les Dockerfiles ou docker-compose.yml
- Multi-stage builds (pas d'outils de build en production)
Secrets
- Pas de
.env versionné (vérifier .gitignore)
- Pas de secrets en dur dans le code (grep pour
password=, secret=, api_key=)
- Historique Git : lancer
gitleaks detect — un secret supprimé du code mais encore dans l'historique Git est toujours exploitable
- Variables d'environnement injectées via CI/CD
- Secret key JWT suffisamment longue
TLS / Reverse Proxy
- HTTPS forcé (redirection HTTP → HTTPS)
- TLS 1.2+ uniquement
- Certificats valides et auto-renouvelés (Let's Encrypt / Caddy auto)
CI/CD
- GitHub Actions pinnées sur des versions exactes (pas
@main)
- Pas de secrets dans les logs de CI
- Images Docker tagguées (pas
latest)
Fichiers sensibles exposés
- Pas de
.env, .git/, __pycache__/, node_modules/ accessibles via HTTP
- Pas de page de debug/admin exposée en production
Commandes automatiques
L'agent chef d'équipe doit lancer ces commandes au début de l'audit pour collecter des données :
# Dépendances Python vulnérables
cd CHEMIN_PROJET/backend && uv run pip-audit 2>/dev/null || echo "pip-audit non disponible"
# Dépendances JS vulnérables (pour chaque frontend)
cd CHEMIN_PROJET/frontend-client && pnpm audit 2>/dev/null || npm audit 2>/dev/null || echo "audit non disponible"
cd CHEMIN_PROJET/frontend-admin && pnpm audit 2>/dev/null || npm audit 2>/dev/null || echo "audit non disponible"
# Secrets en dur dans le code
grep -rn "password\s*=" --include="*.py" --include="*.ts" --include="*.tsx" CHEMIN_PROJET/ | grep -v node_modules | grep -v __pycache__ | grep -v ".env.example"
grep -rn "secret.*=.*['\"]" --include="*.py" --include="*.ts" CHEMIN_PROJET/ | grep -v node_modules | grep -v __pycache__
# Secrets dans l'historique Git (un secret supprimé du code reste dans l'historique)
cd CHEMIN_PROJET && gitleaks detect --source . 2>/dev/null || echo "gitleaks non disponible — installer avec: brew install gitleaks"
# Fichiers .env versionnés
find CHEMIN_PROJET -name ".env" -not -path "*/node_modules/*" -not -path "*/.git/*"
# Vérifier .gitignore
cat CHEMIN_PROJET/.gitignore 2>/dev/null | grep -E "\.env|secret|credential"
# Vérifier que les mots de passe ne sont pas loggés
grep -rn "log.*password\|print.*password\|logger.*password" --include="*.py" CHEMIN_PROJET/ | grep -v node_modules | grep -v __pycache__
Patterns dangereux à chercher (grep)
Chaque agent doit rechercher ces patterns dans son périmètre :
Note : ces patterns sont des heuristiques — un match ne signifie pas forcément une vulnérabilité, et l'absence de match ne garantit pas la sécurité. Par exemple, dangerouslySetInnerHTML avec DOMPurify sur une ligne différente ne sera pas détecté. Chaque match doit être vérifié manuellement dans son contexte.
Backend
localStorage # Ne devrait pas apparaître côté backend
eval( # Exécution dynamique de code
exec( # Exécution dynamique de code
__import__ # Import dynamique
setattr.*request # Mass assignment potentiel
.format(.*password # Log de mot de passe
f".*password # Log de mot de passe
log.*password|print.*password # Password dans les logs
allow_origins.*\* # CORS wildcard
MD5\(|md5\(|sha1\( # Hachage faible
"SELECT.*".*\+|f"SELECT # SQL brut avec concaténation
email.*(inconnu|not found|unknown) # Énumération utilisateurs
Frontend
localStorage.*token # Token dans localStorage
sessionStorage.*token # Token dans sessionStorage
dangerouslySetInnerHTML # Vérifier manuellement que DOMPurify est utilisé (peut être sur une autre ligne)
eval\( # Exécution dynamique
new Function\( # Exécution dynamique
window\.open\( # Vérifier manuellement que l'URL est validée
innerHTML\s*= # XSS potentiel
document\.cookie # Accès direct aux cookies
Format du rapport
Le rapport final (audit-auth-report.md) doit suivre ce format :
# Rapport d'Audit d'Authentification
**Projet** : [nom]
**Date** : [date]
**Auditeur** : Claude Code — Audit Auth Skill
## Résumé exécutif
- X vulnérabilités critiques
- X vulnérabilités élevées
- X vulnérabilités moyennes
- X points d'amélioration
## Score global : X/100
## Findings
### [CRITIQUE] Titre du finding
**Composant** : backend | frontend | infra
**Fichier** : chemin:ligne
**Description** : Description claire du problème
**Impact** : Ce qui pourrait arriver si exploité
**Correctif** :
\```python
# Code correctif concret
\```
**Référence** : OWASP / CWE / CVE si applicable
### [ÉLEVÉ] ...
### [MOYEN] ...
### [FAIBLE] ...
## Audit des dépendances
### Python (pip-audit)
[résultat]
### JavaScript (pnpm audit)
[résultat]
## Checklist OWASP Auth
| Contrôle | Statut | Détail |
|----------|--------|--------|
| Hachage mots de passe | ✅/⚠️/❌ | ... |
| Protection brute-force | ✅/⚠️/❌ | ... |
| ... | ... | ... |
## Recommandations prioritaires
1. [Action immédiate — critique]
2. [Action court terme — élevé]
3. [Action moyen terme — moyen]
Scoring
Le score global est calculé sur 100 points :
| Catégorie |
Points |
Critères |
| Stockage tokens |
/15 |
HttpOnly cookies, pas localStorage, scope, secure, samesite |
| Hachage MDP |
/10 |
Argon2id/bcrypt, pas de clair/MD5/SHA |
| Rate limiting |
/10 |
Présent sur endpoints sensibles, limites raisonnables |
| CORS |
/5 |
Pas de wildcard, headers explicites |
| XSS protection |
/10 |
DOMPurify, CSP, pas d'eval/innerHTML |
| Injection SQL |
/5 |
ORM, pas de requêtes brutes, LIKE échappé |
| Refresh token |
/10 |
Rotation, révocation, vérif user BD |
| Headers HTTP |
/10 |
HSTS, CSP, X-Content-Type, X-Frame |
| Secrets |
/10 |
Pas de secrets en dur, .env ignoré, clé JWT longue, gitleaks clean |
| Docker/Infra |
/5 |
Non-root, versions pinnées, limites resources |
| Dépendances |
/5 |
Pas de CVE connues |
| Mass assignment |
/5 |
ALLOWED_FIELDS ou extra=forbid |
Règle de plafonnement
Un seul finding CRITIQUE plafonne le score à 40/100 maximum, quel que soit le score des autres catégories. Cela évite un faux sentiment de sécurité (ex: score 85 alors qu'un mot de passe est stocké en clair).
- 1+ finding CRITIQUE → score plafonné à 40/100
- 3+ findings ÉLEVÉ → score plafonné à 60/100
- Les plafonds sont cumulatifs : le plus bas s'applique
Sévérité
| Niveau |
Définition |
Exemples |
| CRITIQUE |
Exploitable immédiatement, impact majeur |
Token dans localStorage, MDP en clair, SQL injection, CORS wildcard avec credentials |
| ÉLEVÉ |
Exploitable avec effort modéré, impact significatif |
Pas de rate limiting sur login, pas de refresh token rotation, secrets en dur |
| MOYEN |
Exploitation indirecte ou impact limité |
Headers HTTP manquants, TOTP secret non chiffré, pas de blacklist token |
| FAIBLE |
Bonne pratique non respectée, risque théorique |
Docker en root, images non pinnées, warning HTTPS au lieu de blocage |
1---2name: audit-auth3description: Audit de sécurité complet de l'authentification d'une application (backend + frontend + infra)4---56# Audit Auth — Audit de sécurité d'authentification78Réalise un audit de sécurité complet du système d'authentification d'une application. Analyse le backend, le frontend et l'infrastructure pour identifier les vulnérabilités, les mauvaises pratiques et les améliorations possibles. Produit un rapport structuré avec sévérité et correctifs.910## Variables1112CHEMIN_PROJET: $ARGUMENTS1314## Instructions1516- Si aucun `CHEMIN_PROJET` n'est fourni, STOP et demande à l'utilisateur de le fournir (AskUserQuestion).17- **Utilise le mode team** : crée une équipe avec les agents décrits ci-dessous pour paralléliser l'audit.18- Chaque agent produit ses findings. Le chef d'équipe compile le rapport final.19- Le rapport final doit être sauvegardé dans `CHEMIN_PROJET/audit-auth-report.md`.2021## Équipe d'audit2223Crée une équipe via `TeamCreate` avec les membres suivants. Chaque agent est un `builder` ou `general-purpose`.2425### Agent 1 : `backend-auditor`26**Subagent type** : `general-purpose`27**Mission** : Auditer tout le code backend lié à l'authentification.2829Checklist à vérifier :301. **JWT Configuration**31 - Algorithme (HS256 minimum, RS256 préféré pour microservices)32 - Longueur de la clé secrète (>= 32 chars pour HS256, >= 2048 bits pour RS256)33 - TTL des tokens (access <= 30 min, refresh <= 7 jours)34 - Validation du type de token (access vs refresh vs totp_pending)35 - Présence du claim `exp` vérifié automatiquement36 - Présence du claim `sub` avec UUID valide37382. **Stockage des tokens**39 - Cookies HttpOnly (pas localStorage)40 - Attributs : `secure=True`, `samesite=lax|strict`, paths scopés41 - Refresh token avec path restreint (`/api/auth` pas `/api`)42433. **Hachage des mots de passe**44 - Algorithme : Argon2id (recommandé) ou bcrypt (acceptable)45 - Pas de MD5, SHA1, SHA256 nu, ou stockage en clair46 - `passlib` déprécié — vérifier la lib utilisée47484. **Rate limiting**49 - Présent sur login, register, refresh, reset password, magic link50 - Limites raisonnables (5-10/min par IP)51 - Handler HTTP 429 configuré52535. **Protection mass assignment**54 - `_ALLOWED_FIELDS` ou `extra="forbid"` sur chaque endpoint d'update55 - Pas de `setattr()` sans whitelist56576. **CORS**58 - Pas de `allow_origins=["*"]` avec credentials59 - Méthodes et headers explicites (pas `["*"]`)60617. **Injection SQL**62 - Utilisation d'un ORM (SQLModel/SQLAlchemy)63 - Échappement des wildcards LIKE (`%`, `_`)64 - Pas de requêtes SQL brutes avec f-strings65668. **Gestion des erreurs & anti-énumération**67 - Messages génériques vers le client (pas de stack traces, pas de détails d'API externes)68 - **Énumération d'utilisateurs** : le login doit retourner un message identique que l'email existe ou non (ex: "Identifiants invalides") — jamais "Email inconnu" vs "Mot de passe incorrect"69 - Même principe sur reset password / magic link : "Si cet email existe, un lien a été envoyé"70 - Vérifier que le timing de réponse est constant (pas de shortcut si l'email n'existe pas)71729. **Logs d'authentification**73 - Les tentatives de login échouées sont-elles loggées ? (avec IP, email, timestamp)74 - Les mots de passe ne sont **PAS** loggés (grep `password` dans les appels logger/print)75 - Les tokens JWT ne sont **PAS** loggés en clair76 - Les événements de sécurité (changement MDP, activation 2FA, logout) sont-ils loggés ?777810. **Sessions concurrentes**79 - Existe-t-il une limite sur le nombre de sessions actives par utilisateur ?80 - Si refresh tokens sont stockés en BD : combien peut-on en avoir simultanément ?81 - Pour les apps métier sensibles : envisager une limite (ex: 5 sessions max) avec invalidation de la plus ancienne828312. **Refresh token**84 - Rotation à chaque usage85 - Révocation possible (blacklist ou token family)86 - Vérification user en BD à chaque refresh878813. **2FA / TOTP**89 - Secret stocké (idéalement chiffré)90 - `valid_window` raisonnable (1-2)91 - Rate limiting sur verify-totp929314. **Logout**94 - Suppression des cookies côté serveur95 - Idéalement : invalidation côté serveur (blacklist)969715. **Dépendances Python vulnérables**98 - Lancer `pip-audit` ou `uv run pip-audit` (si disponible)99 - Vérifier les versions de PyJWT, cryptography, bcrypt/argon2-cffi100101### Agent 2 : `frontend-auditor`102**Subagent type** : `general-purpose`103**Mission** : Auditer tout le code frontend lié à l'authentification.104105Checklist à vérifier :1061. **Stockage des tokens**107 - Aucun token dans localStorage, sessionStorage, ou variable JS108 - `credentials: "include"` sur tous les fetch/axios109 - Pas de header `Authorization: Bearer xxx` construit manuellement depuis le client1101112. **Protection XSS**112 - Pas de `dangerouslySetInnerHTML` sans DOMPurify113 - Pas d'`eval()`, `new Function()`, ou `innerHTML` avec données dynamiques114 - CSP header configuré1151163. **Validation des URLs**117 - `isValidDownloadUrl()` ou équivalent avant `window.open()`118 - Blocage des protocoles `javascript:`, `data:`, `file://`119 - `encodeURIComponent()` sur tous les IDs dans les URLs API1201214. **Route guards**122 - Vérification auth sur chaque route protégée123 - Redirection vers /login si non authentifié124 - Pas de contenu flash avant redirection1251265. **Refresh flow**127 - Interception des 401 → refresh → retry128 - Déduplication des appels refresh parallèles129 - Redirection /login si refresh échoue + appel logout serveur1301316. **Vérification HTTPS**132 - Warning ou blocage si protocole != https en production1331347. **Cache React Query / state**135 - `queryClient.clear()` au logout136 - Pas de données sensibles persistées dans le state après logout1371388. **Dépendances JS vulnérables**139 - Lancer `pnpm audit` ou `npm audit`140 - Vérifier les versions de dompurify, react, etc.141142### Agent 3 : `infra-auditor`143**Subagent type** : `general-purpose`144**Mission** : Auditer la configuration infrastructure et les headers de sécurité.145146Checklist à vérifier :1471. **Headers HTTP**148 - `Strict-Transport-Security` (HSTS) avec max-age >= 1 an149 - `Content-Security-Policy` configuré (pas `unsafe-inline` sauf nécessité documentée)150 - `X-Content-Type-Options: nosniff`151 - `X-Frame-Options: DENY` ou `SAMEORIGIN`152 - `Permissions-Policy` restrictif153 - `Referrer-Policy: strict-origin-when-cross-origin`154 - Pas de header `Server` exposé (version du serveur)1551562. **Docker**157 - Conteneurs non-root (`USER appuser`)158 - Images pinnées sur des versions exactes (pas `latest`)159 - Ports non-privilégiés pour nginx/frontends160 - Limites CPU/mémoire définies161 - Pas de secrets dans les Dockerfiles ou docker-compose.yml162 - Multi-stage builds (pas d'outils de build en production)1631643. **Secrets**165 - Pas de `.env` versionné (vérifier .gitignore)166 - Pas de secrets en dur dans le code (grep pour `password=`, `secret=`, `api_key=`)167 - **Historique Git** : lancer `gitleaks detect` — un secret supprimé du code mais encore dans l'historique Git est toujours exploitable168 - Variables d'environnement injectées via CI/CD169 - Secret key JWT suffisamment longue1701714. **TLS / Reverse Proxy**172 - HTTPS forcé (redirection HTTP → HTTPS)173 - TLS 1.2+ uniquement174 - Certificats valides et auto-renouvelés (Let's Encrypt / Caddy auto)1751765. **CI/CD**177 - GitHub Actions pinnées sur des versions exactes (pas `@main`)178 - Pas de secrets dans les logs de CI179 - Images Docker tagguées (pas `latest`)1801816. **Fichiers sensibles exposés**182 - Pas de `.env`, `.git/`, `__pycache__/`, `node_modules/` accessibles via HTTP183 - Pas de page de debug/admin exposée en production184185## Commandes automatiques186187L'agent chef d'équipe doit lancer ces commandes au début de l'audit pour collecter des données :188189```bash190# Dépendances Python vulnérables191cd CHEMIN_PROJET/backend && uv run pip-audit 2>/dev/null || echo "pip-audit non disponible"192193# Dépendances JS vulnérables (pour chaque frontend)194cd CHEMIN_PROJET/frontend-client && pnpm audit 2>/dev/null || npm audit 2>/dev/null || echo "audit non disponible"195cd CHEMIN_PROJET/frontend-admin && pnpm audit 2>/dev/null || npm audit 2>/dev/null || echo "audit non disponible"196197# Secrets en dur dans le code198grep -rn "password\s*=" --include="*.py" --include="*.ts" --include="*.tsx" CHEMIN_PROJET/ | grep -v node_modules | grep -v __pycache__ | grep -v ".env.example"199grep -rn "secret.*=.*['\"]" --include="*.py" --include="*.ts" CHEMIN_PROJET/ | grep -v node_modules | grep -v __pycache__200201# Secrets dans l'historique Git (un secret supprimé du code reste dans l'historique)202cd CHEMIN_PROJET && gitleaks detect --source . 2>/dev/null || echo "gitleaks non disponible — installer avec: brew install gitleaks"203204# Fichiers .env versionnés205find CHEMIN_PROJET -name ".env" -not -path "*/node_modules/*" -not -path "*/.git/*"206207# Vérifier .gitignore208cat CHEMIN_PROJET/.gitignore 2>/dev/null | grep -E "\.env|secret|credential"209210# Vérifier que les mots de passe ne sont pas loggés211grep -rn "log.*password\|print.*password\|logger.*password" --include="*.py" CHEMIN_PROJET/ | grep -v node_modules | grep -v __pycache__212```213214## Patterns dangereux à chercher (grep)215216Chaque agent doit rechercher ces patterns dans son périmètre :217218**Note** : ces patterns sont des **heuristiques** — un match ne signifie pas forcément une vulnérabilité, et l'absence de match ne garantit pas la sécurité. Par exemple, `dangerouslySetInnerHTML` avec DOMPurify sur une ligne différente ne sera pas détecté. Chaque match doit être vérifié manuellement dans son contexte.219220### Backend221```222localStorage # Ne devrait pas apparaître côté backend223eval( # Exécution dynamique de code224exec( # Exécution dynamique de code225__import__ # Import dynamique226setattr.*request # Mass assignment potentiel227.format(.*password # Log de mot de passe228f".*password # Log de mot de passe229log.*password|print.*password # Password dans les logs230allow_origins.*\* # CORS wildcard231MD5\(|md5\(|sha1\( # Hachage faible232"SELECT.*".*\+|f"SELECT # SQL brut avec concaténation233email.*(inconnu|not found|unknown) # Énumération utilisateurs234```235236### Frontend237```238localStorage.*token # Token dans localStorage239sessionStorage.*token # Token dans sessionStorage240dangerouslySetInnerHTML # Vérifier manuellement que DOMPurify est utilisé (peut être sur une autre ligne)241eval\( # Exécution dynamique242new Function\( # Exécution dynamique243window\.open\( # Vérifier manuellement que l'URL est validée244innerHTML\s*= # XSS potentiel245document\.cookie # Accès direct aux cookies246```247248## Format du rapport249250Le rapport final (`audit-auth-report.md`) doit suivre ce format :251252```markdown253# Rapport d'Audit d'Authentification254**Projet** : [nom]255**Date** : [date]256**Auditeur** : Claude Code — Audit Auth Skill257258## Résumé exécutif259- X vulnérabilités critiques260- X vulnérabilités élevées261- X vulnérabilités moyennes262- X points d'amélioration263264## Score global : X/100265266## Findings267268### [CRITIQUE] Titre du finding269**Composant** : backend | frontend | infra270**Fichier** : chemin:ligne271**Description** : Description claire du problème272**Impact** : Ce qui pourrait arriver si exploité273**Correctif** :274\```python275# Code correctif concret276\```277**Référence** : OWASP / CWE / CVE si applicable278279### [ÉLEVÉ] ...280### [MOYEN] ...281### [FAIBLE] ...282283## Audit des dépendances284### Python (pip-audit)285[résultat]286### JavaScript (pnpm audit)287[résultat]288289## Checklist OWASP Auth290| Contrôle | Statut | Détail |291|----------|--------|--------|292| Hachage mots de passe | ✅/⚠️/❌ | ... |293| Protection brute-force | ✅/⚠️/❌ | ... |294| ... | ... | ... |295296## Recommandations prioritaires2971. [Action immédiate — critique]2982. [Action court terme — élevé]2993. [Action moyen terme — moyen]300```301302## Scoring303304Le score global est calculé sur 100 points :305306| Catégorie | Points | Critères |307|-----------|--------|----------|308| Stockage tokens | /15 | HttpOnly cookies, pas localStorage, scope, secure, samesite |309| Hachage MDP | /10 | Argon2id/bcrypt, pas de clair/MD5/SHA |310| Rate limiting | /10 | Présent sur endpoints sensibles, limites raisonnables |311| CORS | /5 | Pas de wildcard, headers explicites |312| XSS protection | /10 | DOMPurify, CSP, pas d'eval/innerHTML |313| Injection SQL | /5 | ORM, pas de requêtes brutes, LIKE échappé |314| Refresh token | /10 | Rotation, révocation, vérif user BD |315| Headers HTTP | /10 | HSTS, CSP, X-Content-Type, X-Frame |316| Secrets | /10 | Pas de secrets en dur, .env ignoré, clé JWT longue, gitleaks clean |317| Docker/Infra | /5 | Non-root, versions pinnées, limites resources |318| Dépendances | /5 | Pas de CVE connues |319| Mass assignment | /5 | ALLOWED_FIELDS ou extra=forbid |320321### Règle de plafonnement322323**Un seul finding CRITIQUE plafonne le score à 40/100 maximum**, quel que soit le score des autres catégories. Cela évite un faux sentiment de sécurité (ex: score 85 alors qu'un mot de passe est stocké en clair).324325- 1+ finding **CRITIQUE** → score plafonné à **40/100**326- 3+ findings **ÉLEVÉ** → score plafonné à **60/100**327- Les plafonds sont cumulatifs : le plus bas s'applique328329## Sévérité330331| Niveau | Définition | Exemples |332|--------|-----------|----------|333| **CRITIQUE** | Exploitable immédiatement, impact majeur | Token dans localStorage, MDP en clair, SQL injection, CORS wildcard avec credentials |334| **ÉLEVÉ** | Exploitable avec effort modéré, impact significatif | Pas de rate limiting sur login, pas de refresh token rotation, secrets en dur |335| **MOYEN** | Exploitation indirecte ou impact limité | Headers HTTP manquants, TOTP secret non chiffré, pas de blacklist token |336| **FAIBLE** | Bonne pratique non respectée, risque théorique | Docker en root, images non pinnées, warning HTTPS au lieu de blocage |