Technique et prévention · 8 min · publié le 8 août 2026

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 ».

Réponse directe

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.

.git exposé dépôt git public site gitdump wordpress

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.

Questions fréquentes

Un `git status` sur le serveur, c'est déjà trop ?

+
Avoir Git sur le serveur n'est pas le problème. Le servir en HTTP, si. Déplacez le dossier hors web, ou niez-le au vhost. Vous pouvez continuer à déployer par Git sans 200.

GitHub est privé. Pourquoi je tournerais les secrets ?

+
Parce que le clone prod, lui, était public, avec tout l'historique local. Le badge « private » sur github.com ne couvre pas `votre-domaine.fr/.git`.

Je peux laisser `.git` et poser un `Deny from all` ?

+
Mieux que le 200. Moins bien que hors DocumentRoot (un vhost mal recopié, un Apache trop permissif, et ça revient). Les deux : deny + hors web si possible.

L'attaquant a commité un webshell dans Git. Je fais quoi ?

+
Vous le retirez de la prod, vous fermez l'entrée, vous ne « revert » pas seulement : le fichier a pu être copié hors Git. Comparez le reste. L'historique documente, il ne nettoie pas.

Un site statique généré, sans PHP, est concerné ?

+
Oui si le générateur a poussé `.git` avec le HTML. Moins de shell, autant de secrets et de code source. Coupez pareil.
À lire ensuite
Fichier .env exposé Archives zip et .sql publics Dépendances Composer / npm WordPress piraté Premiers gestes Déclarer mon site