JB Logo
Guide gratuit

Sécurité minimale vibecoding

Le fichier que tu colles avant de coder. Règles, checklist, commandes tout ce qu’il faut pour ne pas lancer une passoire.

Avant de commencer

Comment organiser tes fichiers .md

Ne colle pas tout dans un seul fichier. Le CLAUDE.md principal est limité à ~200 lignes et il perd en efficacité quand il est trop long. La bonne approche : un fichier maître qui appelle des fichiers spécialisés.

Le principe

Ton CLAUDE.md principal ne sert qu’à une chose : appeler les autres fichiers .md spécialisés. Il reste court, lisible, et l’IA ne perd rien en route.

Le fichier sécurité que tu vas copier ici va dans un fichier séparé, pas dans le CLAUDE.md principal.

Structure recommandée
mon-projet/
├── CLAUDE.md                  # Fichier maître (~50 lignes max)
├── .cursor/rules/             # Ou .claude/rules/ selon ton outil
│   ├── security.md            # ← Ce fichier (les règles de sécurité)
│   ├── stack.md               # Stack technique, conventions de code
│   └── workflow.md            # Process de travail, commandes de build/test
├── .env.local                 # Secrets (jamais commité)
└── src/
CLAUDE.md principal (exemple)
# Mon Projet

## Fichiers de règles
- Sécurité : @.cursor/rules/security.md
- Stack et conventions : @.cursor/rules/stack.md
- Workflow : @.cursor/rules/workflow.md

## Commandes
- Build : npm run build
- Test : npm run test
- Dev : npm run dev

## Important
- Toujours lire les fichiers de règles avant de coder
- Ne jamais modifier les règles sans demander
Fin de session : mise à jour

Avant de fermer ta session (ou avant que le contexte se compacte), demande à l’IA :

Mets à jour tous les fichiers .md avec ce qu’on a fait aujourd’hui. Ajoute les décisions prises, les patterns utilisés, et les erreurs corrigées.

Comme ça, à la prochaine session, l’IA repart avec tout le contexte sans que tu aies à ré-expliquer.

Section 01

Règles à coller dans ton outil

Copie ce bloc dans ton fichier CLAUDE.md, .cursorrules, ou les instructions de ton projet. Compatible Cursor, Claude, Windsurf, Lovable, Bolt, Replit, v0.

CLAUDE.md / .cursorrules
# Règles de sécurité - OBLIGATOIRES

## Secrets & Clés API
- JAMAIS de clé API, token, ou mot de passe en dur dans le code
- TOUS les secrets vont dans un fichier .env.local (jamais commité)
- Le fichier .env doit être dans le .gitignore AVANT le premier commit
- Côté client (React, Next, etc.) : utiliser UNIQUEMENT les variables préfixées correctement (NEXT_PUBLIC_, VITE_, etc.)
- Côté serveur : les clés sensibles (Stripe secret, Supabase service key) ne sont JAMAIS exposées au frontend

## Base de données (Supabase / Firebase)
- Row Level Security (RLS) ACTIVÉ sur TOUTES les tables sans exception
- Chaque table a au minimum 1 policy SELECT, 1 UPDATE, 1 DELETE
- Policy par défaut = RESTRICTIVE (tout est bloqué sauf ce qui est explicitement autorisé)
- Utiliser UNIQUEMENT auth.uid() dans les policies (JAMAIS user_metadata, l’utilisateur peut le modifier)
- La service key Supabase = BACKEND UNIQUEMENT, jamais dans le code client
- En client-side, utiliser UNIQUEMENT la anon key
- Ajouter WITH CHECK sur toutes les policies UPDATE et INSERT
- Créer un index sur user_id pour chaque table avec RLS

## Authentification
- Toute page protégée redirige vers /login si l’utilisateur n’est pas connecté
- Les tokens JWT sont validés côté serveur, pas uniquement côté client
- Le logout invalide la session complètement (pas juste un redirect)
- Les cookies de session : Secure, HttpOnly, SameSite=Strict
- Implémenter un refresh token avec expiration courte (15 min access, 7 jours refresh)

## Inputs utilisateur (injections)
- JAMAIS de concaténation directe dans les requêtes SQL → parameterized queries
  ❌ db.query("SELECT * FROM users WHERE id = " + userId)
  ✅ db.query("SELECT * FROM users WHERE id = $1", [userId])
- JAMAIS de innerHTML ou dangerouslySetInnerHTML avec du contenu utilisateur
- Valider ET sanitizer chaque input côté serveur (pas seulement côté client)
- Échapper tout output affiché dans le HTML

## API & Réseau
- HTTPS obligatoire en production (jamais HTTP)
- CORS restreint : lister les domaines autorisés explicitement
  ❌ Access-Control-Allow-Origin: *
  ✅ Access-Control-Allow-Origin: https://monapp.com
- Rate limiting sur les endpoints sensibles (login, signup, paiement)
- Pas de secrets dans les URLs (?apiKey=xxx → interdit)

## Dépendances & Packages
- Vérifier chaque package ajouté par l’IA dans package.json AVANT de commit
- Lancer npm audit (ou pip audit) régulièrement
- Se méfier des packages peu connus ou récents suggérés par l’IA
- Pas de eval(), pas de Function(), pas d’exécution dynamique de code

## Déploiement
- Variables d’environnement configurées dans le dashboard d’hébergement
- Le fichier .env n’est PAS dans le repo Git
- Tester le parcours complet en staging avant production
- Vérifier qu’aucune erreur n’affiche de stack trace en production
- Headers de sécurité : Content-Security-Policy, X-Frame-Options, Strict-Transport-Security
Section 02

Checklist pré-déploiement

Coche chaque point avant de mettre en ligne. Si un seul rouge n’est pas coché, ne déploie pas.

Secrets & Credentials

Critique
J’ai cherché "password", "key", "token", "secret" dans mon code frontend, aucun résultat
Mon fichier .env est dans .gitignore
Mes clés Stripe/Supabase/Firebase ne sont PAS visibles dans le code client
J’utilise la anon key (pas la service key) côté client

Base de données

Critique
RLS est activé sur TOUTES mes tables Supabase
J’ai testé avec 2 comptes : User A ne voit PAS les données de User B
Mes policies utilisent auth.uid() (pas user_metadata)
J’ai un WITH CHECK sur mes policies INSERT et UPDATE

Authentification

Important
Les pages protégées redirigent bien vers /login si pas connecté
Le logout déconnecte vraiment (pas juste un redirect)
Les tokens sont validés côté serveur

Protection contre les injections

Important
Aucune concaténation de string dans mes requêtes SQL
Pas de innerHTML avec du contenu utilisateur
Les inputs sont validés côté serveur

Réseau & Déploiement

Recommandé
HTTPS activé (le cadenas apparaît dans le navigateur)
CORS ne permet pas "*" (toutes origines)
Les erreurs en production n’affichent pas de stack trace
Variables d’environnement configurées sur l’hébergeur

Dépendances

Recommandé
J’ai lancé npm audit, pas de vulnérabilité critique
J’ai vérifié les packages inconnus dans package.json
Pas de eval() ou Function() dans mon code

Tu as des points non cochés ? Un audit professionnel va bien plus loin qu’une checklist.

Réserver un audit
Section 03

Commandes de vérification

Copie-colle dans ton terminal pour vérifier automatiquement.

bash /Chercher des secrets exposés
# Chercher des clés/tokens/passwords dans le code source
grep -rn "password\|secret\|token\|api_key\|apiKey\|SUPABASE_SERVICE" \
  --include="*.js" --include="*.ts" --include="*.jsx" --include="*.tsx" src/
bash /Vérifier que .env est ignoré
# Si cette commande affiche ton .env, tu as un problème
git ls-files | grep -i "\.env"
bash /Auditer les dépendances
npm audit
# ou
yarn audit
bash /Patterns dangereux
# innerHTML, eval, dangerouslySetInnerHTML
grep -rn "innerHTML\|eval(\|dangerouslySetInnerHTML\|Function(" \
  --include="*.js" --include="*.ts" --include="*.jsx" --include="*.tsx" src/
sql /Vérifier RLS Supabase
-- Dans l’éditeur SQL de Supabase, liste les tables SANS RLS
SELECT schemaname, tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public' AND rowsecurity = false;
-- Si résultats → active RLS dessus immédiatement
Section 04

Les 7 failles les plus courantes

Ce que je vois le plus souvent en auditant des apps vibecodées. Chaque faille avec son fix concret.

Faille #1
La service key Supabase en frontend
Le problème
L’IA met la service key dans le code client. Avec ça, n’importe qui peut bypass le RLS et lire/modifier toute ta base de données.
Le fix
Utilise uniquement la anon key côté client. La service key = backend only.
Faille #2
RLS désactivé ou mal configuré
Le problème
Les tables sont "publiques" par défaut sur Supabase. Sans RLS, un utilisateur peut lire les données de tous les autres utilisateurs.
Le fix
Active RLS sur chaque table + crée des policies restrictives avec auth.uid().
Faille #3
Clés API Stripe en dur dans le code
Le problème
L’IA écrit const stripeKey = "sk_live_..." directement dans un fichier .js. Visible par n’importe qui dans les DevTools.
Le fix
.env.local + variable d’environnement. Jamais de clé dans le code.
Faille #4
Pas de validation côté serveur
Le problème
Les formulaires sont validés uniquement en JavaScript côté client. Un attaquant peut envoyer n’importe quoi directement via l’API.
Le fix
Valide toujours côté serveur. Le frontend c’est pour l’UX, le backend c’est pour la sécurité.
Faille #5
CORS grand ouvert
Le problème
Access-Control-Allow-Origin: * permet à n’importe quel site d’appeler ton API.
Le fix
Liste explicitement les domaines autorisés.
Faille #6
Pas de rate limiting
Le problème
Sans limite, un attaquant peut spam ton endpoint login des milliers de fois par seconde (brute force).
Le fix
Rate limiting sur login, signup, et tout endpoint sensible. La plupart des hébergeurs proposent ça en un clic.
Faille #7
Dépendances fantômes
Le problème
L’IA ajoute des packages npm que personne n’a vérifiés. Certains contiennent du code malveillant.
Le fix
Vérifie chaque nouveau package. S’il a moins de 1 000 téléchargements hebdo, méfiance.

Tu te retrouves dans un de ces cas ? Je peux vérifier ça pour toi.

Réserver un audit
Section 05

Prompt d’audit sécurité

Utilise ce prompt après avoir buildé ta feature, pour demander à l’IA de vérifier la sécurité.

prompt /À coller après chaque build
Fais un audit de sécurité de mon code actuel. Vérifie spécifiquement :

1. SECRETS : est-ce qu’il y a des clés API, tokens, ou mots de passe en dur
   dans le code ? (cherche dans tous les fichiers .js, .ts, .jsx, .tsx, .env)

2. SUPABASE RLS : est-ce que le Row Level Security est activé sur toutes
   les tables ? Est-ce que les policies utilisent auth.uid() et pas
   user_metadata ?

3. INJECTIONS : est-ce qu’il y a des concaténations de strings dans les
   requêtes SQL ? Du innerHTML avec du contenu utilisateur ?

4. AUTH : est-ce que les pages protégées vérifient bien l’authentification ?
   Le logout invalide la session ?

5. CORS : est-ce que les headers CORS sont restrictifs (pas de wildcard *) ?

6. DÉPENDANCES : est-ce qu’il y a des packages suspects ou peu connus dans
   package.json ?

Pour chaque problème trouvé :
- Montre-moi la ligne exacte
- Explique le risque en 1 phrase
- Donne-moi le fix exact à appliquer

Ne fais AUCUNE modification sans mon accord.
Liste d’abord, on corrige ensemble après.

Audit professionnel

Tu développes dans un secteur réglementé ?

Santé, finance, juridique, RH… ou tu as encore des doutes sur la sécurité de ton app. Ce guide couvre les bases, mais un audit complet va beaucoup plus loin.

Réserver un audit
Données brutes / sécurité des apps vibecodées
Code IA contenant des failles de sécurité45%
Code IA avec vulnérabilités connues (CVE)62%
Apps Lovable avec credentials exposées (étude Escape Tech, 1 645 apps)10/38 testées
Apps vibecoded avec failles critiques (même étude)170 / 1 645
Nouvelles CVE liées au code IA, janvier 20266
Nouvelles CVE liées au code IA, février 202615
Nouvelles CVE liées au code IA, mars 202635
Vulnérabilité #1 dans le code IASQL Injection (CWE-89)
Vulnérabilité #2Missing Input Sanitization
Vulnérabilité #3Cryptographic Failures (CWE-327)