"Garde-fou sécurité. Activer dès que le code touche une zone sensible : authentification/sessions, formulaires/entrées utilisateur, requêtes SQL/DB, appels API externes, gestion de secrets/clés, upload de fichiers, génération de HTML/JS dynamique, configuration CORS/CSP/headers. Prévient les failles OWASP Top 10 avant qu'elles n'arrivent en production. Complémentaire avec code-quality (qui couvre l'error handling général). Ne pas activer pour de la logique métier pure sans interaction externe (calculs, algorithmes, transformations de données internes), ni pour du code de test/mock."
Install
npx skillscat add vendeesign/codebloom/security-first Install via the SkillsCat registry.
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) — MD5/SHA1 sont crackables en secondes avec des rainbow tables
- Sessions avec expiration et invalidation — une session éternelle est une porte ouverte permanente
- Tokens JWT : secret fort, expiration courte, refresh token séparé — un JWT volé sans expiration = accès permanent
- Rate limiting sur login/signup — sans rate limiting, le brute force est trivial
- CORS configuré —
*en production expose l'API à n'importe quel site
Entrées utilisateur
- Tout valider côté serveur — la validation front est contournable en une ligne de DevTools
- Sanitiser avant stockage et avant affichage — une entrée non sanitisée est un vecteur XSS ou injection
- Utiliser les validators du framework (Zod, Joi, class-validator, etc.) — éprouvés et maintenus vs regex maison fragile
- Limiter la taille des inputs (longueur, taille fichier) — un input de 10MB peut saturer la mémoire du serveur
// MAL — confiance aveugle
app.post('/search', (req, res) => {
const results = search(req.body.query) // non validé, non limité
})
// BIEN — validé et limité
app.post('/search', (req, res) => {
const { query } = schema.parse(req.body) // Zod/Joi valide et tronque
const results = search(query)
})Base de données
- Requêtes paramétrées — une concaténation de string SQL = injection SQL garantie (OWASP #1)
- ORM/query builder préféré au SQL brut — paramétrage automatique et échappement intégré
- Moindre privilège pour les credentials DB — si l'app est compromise, les dégâts sont limités
- Pas de données sensibles dans les logs — les logs sont souvent accessibles à plus de personnes que la DB
// MAL — injection SQL via concaténation
$wpdb->query("DELETE FROM users WHERE id = $id")
// BIEN — requête préparée
$wpdb->query($wpdb->prepare("DELETE FROM users WHERE id = %d", $id))API externes
- Secrets dans les variables d'environnement — un secret dans le code source finit dans l'historique git, accessible à tous les contributeurs
- HTTPS obligatoire — HTTP en clair expose les tokens et données en transit
- Timeout et gestion d'erreur sur chaque appel — sans timeout, un service lent peut bloquer toute l'application
- Valider les réponses — une API tierce compromise peut injecter des données malveillantes
// MAL — pas de timeout, pas de validation
const data = await fetch(url).then(r => r.json())
// BIEN — timeout + validation de la réponse
const res = await fetch(url, { signal: AbortSignal.timeout(5000) })
if (!res.ok) throw new Error(`API error: ${res.status}`)
const data = schema.parse(await res.json())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— un.envpushé par erreur expose tous les secrets du projet, et l'historique git les garde même après suppression.env.examplesans valeurs réelles — sert de documentation pour l'équipe sans risque de fuite- Pas de clés API, tokens ou mots de passe dans le code source —
git logest public sur les repos open source - Pas de secrets dans les logs, messages d'erreur ou réponses API — les logs sont souvent le premier endroit qu'un attaquant consulte
Patterns sûrs
Au lieu de...
// MAL — injection SQL
db.query(`SELECT * FROM users WHERE id = ${userId}`)
// BIEN — paramétré
db.query('SELECT * FROM users WHERE id = $1', [userId])// MAL — XSS
element.innerHTML = userInput
// BIEN — échappé
element.textContent = userInput// MAL — secret en dur
const API_KEY = "sk-abc123..."
// BIEN — variable d'environnement
const API_KEY = process.env.API_KEYError Handling — Aspect sécurité
- Ne pas exposer au client : stack traces, chemins de fichiers, noms de tables, versions de framework
- Messages d'erreur : informatifs en interne (logs), génériques vers le client
- Pas de secrets dans les erreurs — ni dans les logs, ni dans les réponses API
Pour les bonnes pratiques générales d'error handling (catch vide, fail fast, erreurs async), voir la skill
code-quality.
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