Le dossier .git est en ligne : l'historique du code est public
Un dossier `.git` joignable en HTTP permet de reconstruire le dépôt : historique, parfois des secrets commités. Bloquez l'accès, tournez ce qui a vécu dans Git, considérez les anciens mots de passe comme lus. Fréquent après une mise en prod « on clone et ça tourne ».
On peut reconstruire le dépôt. Bloquez l'accès, tournez les secrets commitées, considérez que les anciens mots de passe ont fuité. Fréquent après une « mise en prod » rapide.
Ce qu'un `.git` public raconte
L'historique du code, les anciens fichiers, les commits de « retrait du mot de passe » qui laissent le mot de passe trois révisions plus tôt, les emails des auteurs, parfois des tokens. Ce n'est pas « un dossier technique ». C'est le film de votre prod.
Même sans outil sophistiqué, un `/.git/config` en 200 confirme l'exposition. Le reste suit. Nous n'expliquons pas comment extraire un dépôt. Nous disons : si `HEAD` ou `config` répond, le dossier sort du web aujourd'hui.
Un attaquant qui a déjà le FTP n'a pas besoin de ça. Le 200 sert à tous les autres, en continu, jusqu'à la coupure. Archives : même famille d'oubli de déploiement.
Comment il arrive sur le web
Clone dans `public_html`, `git init` sur le serveur « pour déployer », thème versionné avec son `.git`, pipeline qui copie trop large. Les hébergeurs mutualisés n'interdisent pas toujours de servir ce dossier. À vous de ne pas le poser là, ou de le nier au serveur web.
Un sous-module, un thème enfant, un plugin maison : plusieurs `.git`. Cherchez-les tous. Un seul 200 suffit.
Headless : le repo front sur Vercel est privé ; une copie WP chez o2switch avec `.git`, elle, est publique. Deux origines. Headless.
Bloquer n'est pas réécrire l'histoire
403 / 404 sur `/.git` (et les variantes), ou mieux : déplacer le dépôt hors DocumentRoot, déployer seulement les fichiers nécessaires. La coupure arrête les nouveaux téléchargements. Elle n'efface pas ce qui a déjà été pris, ni les forks, ni les caches de scanners.
D'où la rotation : tout secret qui a vécu dans le repo, même « retiré depuis ». L'historique Git est long. `.env`.
Ne « videz pas » `.git` en laissant un demi-dépôt cassé si vous en avez besoin pour déployer : déplacez, puis niez l'HTTP. Un `.git` à moitié là se répare mal et se ressert parfois.
- `/.git/HEAD` et `/.git/config` : plus de 200.
- Autres `.git` dans thèmes / plugins.
- Secrets de l'historique : rotation, pas confiance au dernier commit.
Secrets dans l'historique, pas seulement HEAD
Un commit « remove password » est célèbre et insuffisant. Le blob ancien reste. On tourne chez le fournisseur (base, API, SMTP). On ne « squash pas en prod le soir J » pour se rassurer : un rewrite Git mal fait casse le déploiement et n'efface pas les clones déjà partis.
Les clés SSH un jour commitées, les `.env.example` trop réalistes, les dumps « pour tester ». Même passe.
Si le dépôt distant (GitHub, GitLab) est privé mais le `.git` prod est public, l'historique local peut être plus riche (branches, stashes). Traitez le serveur, pas seulement GitHub.
Ce qu'on ne fait pas (et pourquoi)
Pas de tutoriel de dumping. Pas de « pour vérifier, lancez telle commande d'extraction ». Vous vérifiez avec une requête HEAD/GET sur `/.git/HEAD` : 403/404, c'est le critère métier. Si 200, vous coupez, vous ne « téléchargez pas pour voir ».
Pas de nouveau domaine « parce que le code a fuité ». Le code fuité se traite par rotation et par fermeture HTTP. Nouveau domaine.
Pas de refonte dans la foulée. Refonte vs nettoyage.
WordPress, thèmes, et le repo « pour faire pro »
Versionner un thème enfant est sain. Le versionner DANS le DocumentRoot avec `.git` servi, non. Déployez un export, ou un hook qui sort sans métadonnées Git.
Un thème nulled livré avec son `.git` d'origine : hors circuit + historique inconnu. Thème nulled.
Composer / npm : `vendor` et `node_modules` ne sont pas `.git`, mais un `.git` dans une dépendance copiée, si. La passe cherche `**/.git`.
Après : Git hors DocumentRoot
Le workflow : build ailleurs, rsync/artefact sans `.git`, ou bare repo hors web + checkout. Règle serveur explicite contre `/.git`. Test après chaque déploiement.
Invitations GitHub : comme GTM, on révoque les inconnus. Un `.git` public n'empêche pas un collaborateur fantôme sur l'org.
Surveillance : `/.git/HEAD` qui repasse en 200 après un deploy. Surveillance.
Même passe que `.env` et les zip
Une heure, une liste de chemins sensibles. Le piratage « malware » et l'exposition Git se traitent ensemble : souvent le même oubli de mise en prod.
Le constat : URL, dates, si `config` montrait un remote, secrets tournés. Sans coller l'historique Git dans un PDF.
Déclarer : « /.git répondait 200 » suffit. On coupe, on tourne, on cherche encore l'entrée malware si elle est ailleurs. Deux volets, un dossier.