Déboguer comme un pro & sécuriser ton app
Objectifs de ce chapitre
- Protéger tes secrets et réagir correctement à une fuite
- Valider les entrées utilisateur et poser des limites partout
- Diagnostiquer méthodiquement un bug en production
Le soir où tout a failli déraper
Un mardi soir, deux messages tombent coup sur coup. Le premier vient de Karim, un élève à l'humour douteux : « M'sieur, j'ai mis un truc bizarre dans le nom d'une habitude et maintenant la page affiche n'importe quoi 😂 ». Le second vient de la collègue de français : « L'app était très lente hier vers 19 h, c'est normal ? ». Tom réalise une chose que tout créateur d'app découvre un jour : avec de vrais utilisateurs viennent les vrais bugs… et les vraies bêtises. Son app n'est plus un projet personnel, c'est un service public miniature — et un service, ça se sécurise.
Rassure-toi : la sécurité « niveau débutant pro » tient sur trois fronts, et tu as déjà des bases sur chacun. Les secrets (tes clés et mots de passe d'infrastructure), les entrées (tout ce que les utilisateurs tapent), et les limites (ce qu'on a le droit de faire, combien de fois). Ce chapitre fait le tour des trois, puis t'arme pour le débogage en conditions réelles — celui où le bug est chez un utilisateur, sur un appareil que tu n'as pas, à une heure où tu n'étais pas là.
Front 1 — Les secrets
Tu sais déjà que les clés vivent dans un fichier .env côté serveur. Reste à vérifier deux choses. D'abord, que ce fichier est bien ignoré par Git : s'il est commité, il part sur GitHub avec le reste — et un dépôt, même privé aujourd'hui, peut devenir public demain. Ensuite, que tu sais réagir à une fuite : on ne « cache » jamais une clé compromise, on la révoque (on la désactive dans le tableau de bord du service) et on en génère une nouvelle. Toujours, sans exception, même dans le doute.
# .gitignore — à la racine du projet .env .env.local # Vérifier que .env n'est PAS suivi par Git : git status # .env ne doit apparaître nulle part dans la sortie. # Si une clé a fuité : on ne la cache pas, on la RÉVOQUE # dans le tableau de bord du service, et on en génère une nouvelle.
Front 2 — Ne jamais faire confiance aux entrées
Revenons à la blague de Karim. Qu'a-t-il fait ? Il a tapé du code HTML dans le champ « nom d'habitude » — quelque chose comme <h1>COUCOU</h1> — et l'app l'a affiché tel quel, en l'interprétant comme de la mise en page. Drôle ici ; grave en général : si une app affiche sans précaution ce que les utilisateurs saisissent, un utilisateur malveillant peut y glisser du code qui s'exécutera chez les autres. C'est la famille d'attaques la plus courante du web (les initiés disent « XSS »), et la parade s'appelle l'échappement : le texte saisi est toujours affiché comme du texte, jamais interprété comme du code.
Le principe à graver : toute entrée utilisateur est suspecte par défaut. Un nom d'habitude doit être traité comme du texte brut, vérifié en longueur, et validé côté serveur — pas seulement dans le navigateur, car un utilisateur outillé peut contourner tout ce qui se passe côté client. Tu n'as pas à implémenter ça toi-même : tu dois l'exiger et le tester. Le test est simple et savoureux : fais comme Karim, essaie de casser ta propre app.
L’audit de sécurité : ton allié IA
Bonne nouvelle : l'IA est remarquablement douée pour auditer le code qu'elle a elle-même écrit, à condition de lui donner un mandat précis. Voici le prompt d'audit de Tom — garde-le précieusement, il resservira à chaque étape importante de tous tes projets :
Fais un audit de sécurité complet de mon app de suivi d'habitudes, adapté à mon niveau débutant. Contexte : HTML/JS sur Vercel, Supabase avec authentification par lien magique et règles RLS, fonctions serveur pour les e-mails et l'IA, paiement via Stripe Payment Links. Vérifie en priorité : 1. des clés ou secrets présents dans le code côté navigateur, dans le dépôt Git ou dans son historique 2. les entrées utilisateur affichées sans échappement : noms d'habitudes, contenus de formulaires 3. les règles RLS : un utilisateur peut-il lire ou modifier les données d'un autre ? 4. les fonctions serveur : peuvent-elles être appelées sans être connecté ? sans limite de fréquence ? 5. les dépendances ou bibliothèques avec des failles connues Pour chaque problème trouvé : explique le risque en une phrase simple, montre la correction minimale, et classe le tout par gravité de critique à mineur. Ne corrige RIEN sans mon accord explicite, point par point.
Deux exigences font la valeur de ce prompt. Le classement par gravité : tu traites d'abord le critique, et tu décides en connaissance de cause pour le reste — toutes les failles ne se valent pas, et un débutant qui veut tout corriger d'un coup ne corrige rien de bien. Et le « ne corrige rien sans mon accord » : un audit qui modifie le code en même temps qu'il l'analyse est incontrôlable. D'abord comprendre, ensuite corriger, une correction à la fois — la méthode du chapitre 4 s'applique aussi à la sécurité.
Front 3 — Poser des limites partout
Troisième front, le plus simple à comprendre : tout ce qui n'a pas de limite explicite finira par être poussé à l'absurde — par malice, par accident, ou par un robot. Au chapitre 8, tu as limité les e-mails et les appels IA ; généralise maintenant le réflexe à toute l'app. Chaque champ a une longueur maximale, chaque liste a une taille maximale, chaque action a une fréquence maximale. Et chaque refus s'accompagne d'un message poli et clair — la limite protège, elle ne punit pas.
- Nom d'habitude : 50 caractères maximum, texte brut uniquement.
- Nombre d'habitudes par compte : 30 maximum — personne n'en suit 200, mais un script peut en créer 100 000.
- Récap e-mail : 1 envoi par utilisateur et par jour.
- Message IA : 1 appel par utilisateur et par jour, plafond de dépense mensuel chez le fournisseur.
- Création de compte : protégée par la vérification d'e-mail du lien magique — déjà en place, merci le chapitre 6.
flowchart TD
E["Entrée ou action utilisateur"] --> V{"Contenu valide ?"}
V -->|"Non"| R["Message d'erreur clair et poli"]
V -->|"Oui"| L{"Dans les limites ?"}
L -->|"Non"| R2["Refus expliqué : limite atteinte"]
L -->|"Oui"| S["Traitement et stockage en sécurité"]Déboguer en production : la méthode
Reste le message de la collègue : « c'était lent hier vers 19 h ». Bug typique de production : tu ne l'as pas vu, tu ne peux pas le reproduire à volonté, et l'utilisateur ne donne presque aucun détail. La méthode pro tient en trois mouvements : collecter (poser à l'utilisateur les bonnes questions : quel appareil, quel navigateur, quelle heure, quelle action précise, une capture d'écran), consulter (les journaux — « logs » — de Vercel et Supabase, qui enregistrent ce qui s'est réellement passé sur le serveur à cette heure-là), et conjecturer (formuler des hypothèses classées, puis les tester une à une, de la plus simple à la plus complexe).
Bug en production à diagnostiquer méthodiquement. Contexte : un élève me dit que l'app « efface ses coches » sur son téléphone Android avec Chrome, hier vers 19 h. Sur mon ordinateur, impossible de reproduire. Ce dont je dispose : les logs Vercel de la soirée, l'accès au tableau de bord Supabase, et la possibilité de réécrire à l'élève. Guide-moi en trois temps : 1. la liste exacte des questions à poser à l'élève pour cerner le contexte 2. quoi chercher précisément dans les logs Vercel et dans les données Supabase autour de 19 h 3. comment simuler un mobile Android et un réseau lent depuis mon navigateur pour tenter de reproduire Propose ensuite tes 3 hypothèses les plus probables, classées de la plus simple à vérifier à la plus complexe, avec le test à faire pour chacune.
Remarque la structure : ce prompt ne demande pas une solution, il demande une enquête. C'est le bon réflexe face à un bug non reproduit — chercher la correction avant d'avoir cerné la cause, c'est corriger au hasard. Les « 3 hypothèses classées » t'évitent l'autre piège : explorer la piste exotique avant la piste banale. Dans la vraie vie, l'hypothèse banale gagne neuf fois sur dix : un réseau qui coupe au mauvais moment, une vieille version en cache, une session expirée.
La sauvegarde, ton assurance-vie
Dernière pièce du dispositif : la sauvegarde des données. Ton code est en sécurité dans Git, mais les habitudes et les coches de tes utilisateurs ne vivent que dans la base. Une fausse manœuvre dans le tableau de bord — une table vidée d'un clic trop rapide — et tout disparaît. Vérifie ce que ton plan Supabase sauvegarde automatiquement, et complète avec un export régulier (l'IA peut te créer un petit script d'export, ou utilise la fonction d'export du tableau de bord). Et surtout, fais une fois l'exercice de restauration : une sauvegarde jamais testée est une promesse, pas une protection.
Avec ses trois fronts couverts, son journal d'incidents entamé et sa première sauvegarde testée, Tom dort mieux. Karim a reçu un message poli (« nom d'habitude invalide 😉 »), la lenteur de 19 h s'est révélée être un réseau d'internat saturé — hypothèse banale, comme prévu. L'app est solide. Il est temps de la regarder autrement : non plus comme un projet, mais comme un produit. C'est le chapitre final.
Contexte
Tom consacre une soirée complète à la revue de sécurité : audit par l'IA, corrections par gravité, limites partout, et premier test de restauration de sauvegarde. En prime, il s'offre le plaisir de jouer les Karim : essayer de casser sa propre app avant que quelqu'un d'autre ne s'en charge. Déroule le même programme sur ton app — c'est la soirée la plus rentable de ton parcours.
Consignes
- Vérifie tes secrets : .env dans le .gitignore, git status propre, et recherche « key » dans les sources côté navigateur (F12).
- Joue les attaquants : tape du HTML dans tes champs, des textes de 5000 caractères, clique frénétiquement — note tout ce qui casse.
- Lance le prompt d’audit de sécurité complet et lis le rapport en entier avant de corriger quoi que ce soit.
- Corrige les problèmes par gravité décroissante, UNE correction à la fois, avec test et commit après chacune.
- Pose tes limites (longueurs, quantités, fréquences) avec des messages de refus polis, et teste chaque limite.
- Exporte une sauvegarde de ta base, puis fais l’exercice de restauration sur un projet de test — et note la procédure dans ton journal.
En résumé
- Trois fronts : les secrets, les entrées utilisateur, les limites — couvre les trois et tu élimines l’essentiel du risque.
- Une clé qui a touché Git est compromise pour toujours : on révoque et on régénère, on ne « cache » jamais.
- Toute entrée utilisateur est suspecte : échappée à l’affichage, validée côté serveur, limitée en longueur.
- L’audit IA fonctionne avec un mandat précis : périmètre, classement par gravité, et aucune correction sans ton accord.
- Chaque champ, liste et action reçoit une limite explicite, avec un message de refus poli.
- Bug en production : collecter le contexte, consulter les logs, conjecturer des hypothèses classées du banal vers l’exotique.
- Une sauvegarde jamais restaurée est une promesse, pas une protection : teste la restauration une fois.
Quiz — vérifie ta compréhension
1. Tu découvres qu’une clé API a été poussée sur GitHub il y a une semaine. Que fais-tu ?
2. Karim tape du HTML dans un champ et la page l’interprète. Comment s’appelle la parade ?
3. Pourquoi valider les entrées côté serveur et pas seulement dans le navigateur ?
4. Quelles sont les deux exigences clés du prompt d’audit de sécurité ?
5. Un utilisateur signale un bug que tu ne peux pas reproduire. Par quoi commences-tu ?