Security First — Prévention en amont
Ce skill s'active quand du code touche à des zones sensibles, pour prévenir les failles avant la review.
Zones de déclenchement
- •Authentification et sessions
- •Entrées utilisateur (formulaires, query params, headers)
- •Requêtes SQL ou base de données
- •Appels à des API externes
- •Gestion de secrets (clés API, tokens, mots de passe)
- •Upload et manipulation de fichiers
- •Génération de HTML/JS dynamique
- •Configuration CORS, CSP, headers de sécurité
Checklists par contexte
Authentification
- •Mots de passe hashés (bcrypt, argon2) — jamais en clair, jamais MD5/SHA1
- •Sessions avec expiration et invalidation
- •Tokens JWT : secret fort, expiration courte, refresh token séparé
- •Rate limiting sur login/signup
- •CORS configuré — pas de
*en production
Entrées utilisateur
- •Tout valider côté serveur — la validation front ne suffit pas
- •Sanitiser avant stockage et avant affichage
- •Utiliser les validators du framework (Zod, Joi, class-validator, etc.)
- •Limiter la taille des inputs (longueur, taille fichier)
Base de données
- •Requêtes paramétrées — jamais de concaténation de strings SQL
- •ORM/query builder préféré au SQL brut
- •Principes de moindre privilège pour les credentials DB
- •Pas de données sensibles dans les logs
API externes
- •Secrets dans les variables d'environnement — jamais dans le code
- •HTTPS obligatoire
- •Timeout et gestion d'erreur sur chaque appel
- •Valider les réponses (ne pas faire confiance aveuglément)
Fichiers
- •Valider le type MIME (pas seulement l'extension)
- •Limiter la taille
- •Renommer les fichiers uploadés (pas de noms utilisateur)
- •Stocker hors du répertoire web si possible
Secrets et configuration
- •
.envdans.gitignore— toujours - •
.env.examplesans valeurs réelles - •Pas de clés API, tokens ou mots de passe dans le code source
- •Pas de secrets dans les logs, messages d'erreur ou réponses API
Patterns sûrs
Au lieu de...
code
// MAL — injection SQL
db.query(`SELECT * FROM users WHERE id = ${userId}`)
// BIEN — paramétré
db.query('SELECT * FROM users WHERE id = $1', [userId])
code
// MAL — XSS element.innerHTML = userInput // BIEN — échappé element.textContent = userInput
code
// MAL — secret en dur const API_KEY = "sk-abc123..." // BIEN — variable d'environnement const API_KEY = process.env.API_KEY
Error Handling — Gestion d'erreurs sûre
Les erreurs mal gérées sont une faille de sécurité ET de fiabilité.
Anti-patterns
code
// MAL — try/catch vide (erreur silencieuse)
try { await api.call() } catch (e) {}
// MAL — message générique inutile
catch (e) { throw new Error("Something went wrong") }
// MAL — stack trace exposée au client
catch (e) { res.status(500).json({ error: e.stack }) }
// MAL — log sans contexte
catch (e) { console.log(e) }
Patterns corrects
code
// BIEN — gestion explicite avec contexte
try {
await api.call()
} catch (error) {
logger.error('API call failed', { endpoint, userId, error: error.message })
throw new AppError('SERVICE_UNAVAILABLE', 'External service is down')
}
Règles d'error handling
- •Jamais de catch vide — au minimum logger
- •Messages d'erreur : informatifs en interne, génériques vers le client
- •Ne pas exposer : stack traces, chemins de fichiers, noms de tables, versions
- •Distinguer erreurs attendues (validation, 404) et inattendues (crash, timeout)
- •Fail fast — détecter tôt, remonter clairement
- •Erreurs async — toujours un catch sur les Promises, try/catch sur async/await
Comportement
- •Signaler immédiatement les failles détectées — ne pas attendre la review
- •Proposer le fix — pas juste pointer le problème
- •Ne pas sur-sécuriser — adapter au contexte (prototype vs production)
- •Traiter les erreurs mal gérées comme des failles — pas des suggestions
- •En doute sur un pattern → chercher la recommandation OWASP