1. Des clés API intégrées dans le JavaScript de votre frontend
C’est l’erreur la plus dommageable et la plus facile à commettre. Vous demandez à votre outil IA d’« ajouter les paiements Stripe » ou de « se connecter à OpenAI », et il câble la clé secrète directement dans un composant client. L’app fonctionne — et votre clé secrète est désormais livrée au navigateur de chaque visiteur, lisible par quiconque ouvre les DevTools ou fouille votre bundle JS.
Tout ce qui porte le préfixe NEXT_PUBLIC_ (ou VITE_, ou REACT_APP_) est intégré dans le bundle client au moment du build. Les clés secrètes — sk_live_ de Stripe, sk- d’OpenAI, URL de bases de données, clés service role — ne doivent jamais être lues que dans du code côté serveur : API routes, composants serveur ou fonctions edge.
La vérification rapide : ouvrez votre site déployé, affichez le code source de la page et le JS empaqueté, et cherchez sk_live, sk- et les premiers caractères des clés de votre .env. Si l’une d’elles apparaît, renouvelez d’abord la clé, puis déplacez l’appel côté serveur.
2. .env ou .git servis directement depuis votre web root
Un nombre surprenant d’apps déployées renvoient volontiers leur fichier .env — ou leur répertoire .git complet — si vous le demandez simplement. Il suffit d’un serveur de fichiers statiques mal configuré ou d’un template de framework qui copie tout dans le dossier public.
L’impact est total : identifiants de base de données, secrets d’authentification, clés API, le tout dans un seul fichier. Un répertoire .git exposé est presque aussi grave, car un attaquant peut reconstituer tout votre historique de code, y compris les secrets qui ont été commités puis « supprimés ».
La vérification rapide prend dix secondes :
curl -i https://yourapp.com/.env
curl -i https://yourapp.com/.git/config
# Both should return 404 (or 403) — never 200.Fichiers .env exposés : le guide complet3. Pas de Content-Security-Policy
Les outils IA n’ajoutent presque jamais d’en-têtes de sécurité, et la CSP est celui qui compte le plus. Sans elle, un seul bug d’injection de HTML ou de XSS n’importe où dans votre app permet à un attaquant d’exécuter du JavaScript arbitraire dans les navigateurs de vos utilisateurs — volant des sessions et exfiltrant des données.
Une bonne politique de départ pour la plupart des apps : default-src 'self', bloquer les objets et l’intégration en frame, et n’autoriser que les origines de scripts tiers que vous utilisez réellement. Commencez strict, assouplissez délibérément — jamais l’inverse.
// next.config.js
const csp = [
"default-src 'self'",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data:",
"base-uri 'none'",
"frame-ancestors 'none'",
"object-src 'none'",
].join("; ");
module.exports = {
async headers() {
return [{ source: "/:path*", headers: [{ key: "Content-Security-Policy", value: csp }] }];
},
};La CSP expliquée : directives, nonces et erreurs courantes4. Cookies de session sans Secure, HttpOnly et SameSite
Si votre librairie d’authentification a été câblée par un outil IA avec les options par défaut, il vaut la peine de vérifier les flags du cookie de session. Un cookie sans HttpOnly peut être lu par n’importe quel script injecté (transformant un petit XSS en prise de contrôle totale du compte), un sans Secure peut fuiter en HTTP en clair, et un sans SameSite facilite grandement la falsification de requête intersite.
Ouvrez DevTools → Application → Cookies sur votre app déployée. Chaque cookie de session ou d’authentification devrait afficher les trois : Secure, HttpOnly et SameSite=Lax (ou Strict).
5. HTTP qui ne devient jamais HTTPS (et pas de HSTS)
La plupart des plateformes d’hébergement vous donnent HTTPS automatiquement — mais beaucoup d’apps répondent encore volontiers en HTTP en clair sans rediriger, ou redirigent mais n’envoient jamais d’en-tête Strict-Transport-Security. Dans les deux cas, un utilisateur qui tape votre domaine dans la barre d’adresse fait sa première requête sans chiffrement, et cette requête peut être interceptée ou rétrogradée avant que votre redirection n’ait lieu.
La solution tient en deux lignes de configuration : une redirection permanente 301 de HTTP vers HTTPS, plus un en-tête HSTS (max-age=31536000; includeSubDomains) pour que les navigateurs refusent de rétrograder à nouveau.
6. CORS configuré pour tout autoriser
Quand un frontend généré par IA n’arrive pas à atteindre sa propre API pendant le développement, la « solution » qui est générée est presque toujours Access-Control-Allow-Origin: * — parfois avec les credentials autorisés en plus. Cela indique à tous les sites web d’internet qu’ils peuvent appeler votre API depuis le navigateur de leurs visiteurs.
Pour une API qui sert votre propre frontend, l’origine autorisée devrait être exactement votre propre domaine, et rien d’autre. Le CORS générique n’est acceptable que pour des API réellement publiques, sans authentification et en lecture seule.
7. Pas de SPF ni de DMARC sur votre domaine
Celui-ci n’a rien à voir avec le code de votre app — il concerne votre domaine. Sans enregistrements DNS SPF et DMARC, n’importe qui peut envoyer un e-mail prétendant venir de [email protected], et les serveurs de réception n’ont aucun moyen de savoir qu’il est falsifié. C’est du phishing contre vos propres utilisateurs, sous votre marque.
Deux enregistrements DNS TXT le corrigent. Si vous envoyez vos e-mails via un fournisseur comme Resend, Postmark ou SES, leur documentation vous donne la valeur SPF exacte ; ajoutez une politique DMARC à côté et durcissez-la de p=none à p=quarantine une fois que vous avez confirmé que le courrier légitime passe.
Vérifiez les sept en une seule passe
Chaque point de cette liste est détectable de l’extérieur, ce qui veut dire que vous n’avez pas à le passer en revue à la main. AppSafe exécute toutes ces vérifications — plus SSL/TLS, subdomain takeover, source maps et plus — en un seul scan, note le résultat de A à F, et vous donne un prompt de correction IA pour chaque résultat, que vous pouvez coller directement dans Cursor ou Claude Code.
Le scan rapide de la page d’accueil ne nécessite aucune inscription. Le scan complet (y compris les vérifications de secrets exposés) ne s’exécute que sur les domaines dont vous avez vérifié la propriété — par conception, puisque nous n’allons pas fouiller les bundles JS de quelqu’un d’autre à la recherche de clés.