Claude Code m’a écrit « c’est ma faute » : 24 heures avec un mot de passe MySQL en libre accès

Hier soir, j’ai demandé à Claude Code de vérifier la sécurité d’un de mes SaaS après une bascule Stripe en production. Je m’attendais à un rapport rassurant. J’ai eu un rapport honnête. Ce n’est pas la même chose.

Ce qu’il a trouvé

Le rapport comportait une section intitulée, mot pour mot, « Le vrai problème, et c’est ma faute ». La voici, puis je la résume.

Capture d'écran du rapport Claude Code : section « Le vrai problème, et c'est ma faute »
Le rapport, tel qu’il est sorti de Claude Code le 18 août 2026 au soir. Je n’ai rien retouché.

Pour vérifier la configuration du serveur, il a déposé un fichier sonde à la racine web avec une extension inconnue. Le serveur l’a servi tel quel, en HTTP 200, avec son contenu. Autrement dit : tout fichier qui n’est ni du PHP ni un type explicitement bloqué est téléchargeable par n’importe qui.

Ensuite il a relié ce constat à son propre travail de la veille. Le script de bascule Stripe, qu’il avait écrit lui-même, créait une sauvegarde config.php.bak-20260817-191954 avant de modifier la configuration. Et cette sauvegarde, il l’avait écrite exactement là où il ne fallait pas : dans la racine web.

Pendant environ 24 heures, ce fichier contenait, en clair et accessible depuis internet :

  • le mot de passe MySQL
  • l’ancien client secret Google
  • les clés Stripe de test
  • la clé de chiffrement des données de l’application

La seule bonne nouvelle : la clé Stripe live n’y était pas, puisque la sauvegarde précède la bascule.

La phrase qui m’a marqué

La documentation du projet (que Claude Code a lui-même contribué à rédiger) avertit en section 11 de ne jamais laisser de config.php.bak* dans la racine web. Son commentaire dans le rapport : « Mon script l’a fait quand même. Je n’ai pas d’excuse : j’aurais dû écrire cette sauvegarde hors racine. »

Je ne sais pas combien de prestataires humains m’auraient écrit ça spontanément, sans que j’aie à poser la question.

Ce qu’il a corrigé avant de me prévenir

Le rapport ne s’arrêtait pas au constat. Au moment où je l’ai lu, c’était déjà réglé :

  • la sauvegarde déplacée hors de la racine web, en permissions 600
  • un _index.html résiduel retiré
  • trois autres sauvegardes de code (api.php.bak-sec, lib.php.bak-sec, api.php.bak-avant-tva) déplacées elles aussi, puisqu’il n’y avait aucune raison qu’elles soient là non plus
  • le .htaccess durci pour bloquer les fichiers commençant par _ et les extensions résiduelles
  • une vérification par sonde après déploiement : 403 sur les deux motifs bloqués, 200 sur index.php et sur l’API

Puis il m’a listé ce que je devais faire changer, par ordre de priorité. La rotation des secrets exposés en tête, évidemment. Le mot de passe MySQL, le client secret Google (déjà remplacé, mais l’ancien traînait encore), la clé de chiffrement. Ce dernier point est le plus lourd : changer une clé de chiffrement, c’est rechiffrer les données existantes, pas juste éditer une ligne.

Ce que j’en retiens pour le vibe coding en production

Premier point, le plus inconfortable : l’outil qui a créé le problème est le même qui l’a détecté, expliqué et corrigé. On peut y voir un argument pour ou contre, selon l’humeur. Moi j’y vois surtout un rappel que la qualité du résultat dépend de ce qu’on lui demande de vérifier. J’avais demandé une bascule Stripe. Je n’avais pas demandé « et vérifie que tes propres fichiers temporaires ne sont pas exposés ». Il l’a fait parce que je lui ai demandé un audit après coup. Si je ne l’avais pas fait, le fichier serait encore là.

Deuxième point : la doc ne protège de rien si elle n’est pas injectée dans le contexte au bon moment. La règle était écrite. Elle n’a pas été appliquée parce que le script de bascule a été généré dans une session qui ne l’avait pas sous les yeux. C’est exactement le genre de règle qui doit vivre dans un fichier d’instructions projet (CLAUDE.md ou équivalent), pas dans une section 11 d’une documentation que personne ne relit avant chaque tâche.

Troisième point : un serveur qui sert tout fichier d’extension inconnue, c’est une configuration par défaut sur beaucoup d’hébergements mutualisés. Le vrai problème n’était pas le .bak, c’était que je n’avais jamais vérifié ce comportement. Une sonde de dix secondes suffisait. Elle est maintenant dans ma checklist de mise en production, et dans le fichier d’instructions du projet.

Quatrième point, et c’est celui qui m’a décidé à écrire cet article : je n’aurais probablement jamais su. Sans cette phrase « et c’est ma faute », le fichier aurait été corrigé discrètement ou pas du tout, et je n’aurais pas fait tourner les secrets. Un outil qui admet ses erreurs vaut plus qu’un outil qui n’en fait pas en apparence.

Si vous êtes dans le même cas

Trois choses à faire ce soir, dans cet ordre :

  1. Déposez un fichier test.bak-xyz à la racine de votre site et ouvrez-le dans un navigateur. Si vous voyez son contenu, votre serveur sert tout ce qu’il ne connaît pas.
  2. Cherchez les *.bak*, *.old, *.orig, *~ et autres résidus dans votre racine web. Les scripts de déploiement adorent en laisser.
  3. Mettez vos règles de sécurité non négociables dans le fichier d’instructions que votre assistant de code lit à chaque session, pas dans la doc.

Et la prochaine fois que votre assistant vous rend un rapport trop propre, demandez-lui ce qui est de sa faute. Vous serez peut-être surpris de la réponse.

Retour en haut