# Veřejná složka .git: podceňovaný únik dat

> Je vaše složka .git veřejná? Jak to ověřit, zablokovat přístup, změnit nasazování a naložit s přístupovými údaji z historie. S kontrolními příkazy.

Zdroj: https://phpsos.de/cs/blog/git-ordner-oeffentlich/  
Stav: 25.10.2026  
Poskytovatel: PHP SOS, Nouzová pomoc pro PHP a bezpečnost serverů. Okamžitá pomoc přes WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20den%2C%20PHP%20SOS%2C%20pot%C5%99ebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20PHP%20serverem.%20Firma%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručně:** Veřejná složka .git vzniká, když se web nasazuje pomocí `git clone` nebo `git pull` přímo ve webrootu a webserver neblokuje skryté složky. Pak lze stáhnout kompletní zdrojový kód včetně historie verzí, i s dříve vloženými přístupovými údaji. Své domény zkontrolujte jednoduchým požadavkem, přístup okamžitě zablokujte, nasazování převeďte na balíčky bez `.git` a přístupové údaje z historie vyměňte.

## Zdrojový kód k odnesení

Git je standardní nástroj pro správu verzí a pro malé týmy je logické jím také nasazovat: připojit se na server, `git pull`, hotovo. Funguje to spolehlivě a rychle. Má to ale vedlejší účinek, kterého si často nikdo nevšimne.

V adresáři projektu leží skrytá složka `.git`. Neobsahuje jen aktuální stav, ale každý soubor v každé verzi, která kdy byla vložena, k tomu zprávy commitů, jména a e-mailové adresy vývojářů a odkazy na servery. Pokud tato složka leží ve webrootu a webserver ji doručuje, může si ji stáhnout kdokoli.

Pro útočníky je to dárek. Se zdrojovým kódem lze slabiny hledat cíleně, místo aby se hádaly zvenčí. A v historii se často najde to, co se zdálo dávno smazané: heslo k databázi z počátků, klíč API, testovací soubor se zákaznickými daty.

## Je vaše složka .git veřejná? Jak to ověřit

Kontrola trvá sekundy a nic nemění. Pro každou doménu a subdoménu zavolejte soubor, který existuje v každém repozitáři Git:

```bash
# Očekáváno: 403 nebo 404
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.git/HEAD
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.git/config
# Na serveru: Existují složky .git pod webrooty?
find /var/www /srv/www -maxdepth 4 -type d -name ".git" 2>/dev/null
```

Stav 200 znamená: složka je dostupná. Dávejte pozor i na podadresáře. Někdy repozitář neleží přímo ve webrootu, ale ve složce pluginu nebo šablony, která se spravuje samostatně přes Git.

Zkontrolujte také stagingová a testovací prostředí. Aktualizují se přes Git častěji než produkce a bývají dostupná na snadno uhodnutelných subdoménách.

## Okamžitě: zablokovat přístup

Než se nasazování změní, zablokuje přístup ke složkám správy verzí pravidlo ve webserveru. Obecné blokování skrytých souborů, jak je popsáno v článku [Správná ochrana přístupových údajů a souborů .env](https://phpsos.de/cs/blog/env-dateien-schuetzen/), to pokrývá také. Kdo chce zablokovat cíleně jen správu verzí, použije užší pravidlo:

```nginx
location ~ /\.(git|svn|hg)(/|$) {
    return 404;
}
```

```apache
RedirectMatch 404 /\.(git|svn|hg)(/|$)
```

Poté kontrolu shora zopakujte, a to skutečným požadavkem zvenčí: úspěšný test konfigurace říká jen to, že syntaxe sedí, ne že pravidlo zabírá dříve než jiná pravidla pro statické soubory. U panelů jako Plesk nebo cPanel zapište pravidlo do určených dodatečných direktiv, aby se při příštím generování konfigurace neztratilo.

> **Jednejte ihned:**
> Pokud byla složka dostupná, považujte všechny přístupové údaje, které kdy v repozitáři byly, za známé. Samotné blokování pak nestačí, hodnoty je nutné vyměnit.

## Trvale: nasazovat bez .git ve webrootu

Blokování je zabezpečení, ne řešení. Trvale nepatří správa verzí na produkční server. Osvědčené cesty podle vašeho prostředí:

| Postup | Jak funguje | Vhodné pro |
|---|---|---|
| Sestavený balíček z CI | Pipeline vytvoří archiv bez `.git`, server ho rozbalí do nového adresáře vydání | týmy s CI/CD |
| `git archive` | vytvoří archiv stavu bez dat verzí | malé projekty bez pipeline |
| `rsync` s vyloučeními | přenese jen nutné soubory | klasické servery |
| Image kontejneru | kód se při sestavení zkopíruje do image, `.git` se vyloučí přes `.dockerignore` | provoz v kontejnerech |

Adresář vydání pro každou verzi se symbolickým odkazem na aktuální stav má další výhodu: při problémech můžete okamžitě přepnout zpět. Pro prostředí kontejnerů popisuje článek [CI/CD: automatické přestavování image PHP](https://phpsos.de/cs/blog/php-images-in-ci-neu-bauen/), jak učinit sestavení reprodukovatelnými. Tam by se také mělo kontrolovat, že se `.git` do image nedostane.

```bash
# Příklad: vytvořit balíček stavu bez dat verzí
git archive --format=tar.gz -o release.tar.gz HEAD
```

## Další soubory projektu, které nepatří do webrootu

Složka `.git` je nejznámějším příkladem, ale ne jediným. Kdo nasazuje celé adresáře projektu, přináší do webrootu další soubory, které tam nemají co dělat:

- Složky vývojových prostředí jako `.idea` nebo `.vscode`, v nichž rozšíření pro nahrávání souborů někdy ukládají adresy serverů a přístupové údaje.
- `composer.json` a `composer.lock`, které prozrazují přesné verze všech knihoven a usnadňují tak hledání známých zranitelností.
- Konfigurace testů, nástrojů pro sestavení a pipeline, které odhalují interní názvy hostitelů a postupy.
- Zbytky operačních systémů jako `.DS_Store`, které obsahují seznamy souborů celých adresářů.

Řešení je stejné jako u složky `.git`: doručovat jen to, co musí být veřejné, ideálně přes vlastní podsložku jako webroot. Kdo nasazování stejně převádí na balíčky, určí při tom rovnou seznam vyloučených souborů a kontroluje ho při každém novém nástroji v projektu.

## Pokud byla složka otevřená: zkontrolujte historii a logy

Pokud se ukáže, že složka `.git` byla dostupná, postupujte v tomto pořadí:

1. **Zablokujte přístup** a kontrolu zopakujte.
2. **Prohledejte historii**, jaká tajemství byla kdy vložena: konfigurační soubory, `.env`, klíče, výpisy databází.
3. **Vyměňte přístupové údaje**, a to všechny nalezené v kroku 2, i když dnes v kódu už nejsou.
4. **Vyhodnoťte přístupové logy**, zda byly soubory pod `/.git/` staženy se stavem 200 a z jakých adres. Jak na to, ukazuje [Vyhodnocení logů webserveru po útoku](https://phpsos.de/cs/ratgeber/logfiles-auswerten/).
5. **Cíleně zkontrolujte zdrojový kód**, protože útočníci ho nyní znají. Známé slabiny by se měly odstranit přednostně.
6. **Ujasněte ochranu osobních údajů**, pokud v historii ležely osobní údaje, například testovací exporty. Posouzení provede váš pověřenec pro ochranu osobních údajů.

Nástroje pro vyhledávání tajemství v repozitářích patří poté trvale do pipeline. OWASP takové kontroly výslovně doporučuje, jako hook před vložením a v CI.

## Jak konkrétně pomáhá PHP SOS?

- Zkontrolujeme všechny vaše domény a subdomény na dostupné složky správy verzí.
- Přístup okamžitě zablokujeme a nasazování převedeme na balíčky bez dat verzí.
- Prohledáme historii na tajemství a doprovodíme výměnu dotčených přístupů.
- Vyhodnotíme přístupové logy a zdokumentujeme, zda a kdy byla data stažena.

Tato opatření jsou součástí našeho [hardeningu serveru pro webservery s PHP](https://phpsos.de/cs/leistungen/server-haertung/).


## Časté dotazy

**Jak vzniká veřejná složka .git?**  
Většinou nasazením pomocí git clone nebo git pull přímo ve webrootu. Složka .git s celou historií verzí pak leží vedle index.php a bez blokování webserver její soubory doručuje.

**Stačí složku .git smazat?**  
Pro budoucnost ano, pro minulost ne. Pokud byla složka dostupná, mohl být obsah už zkopírován. Přístupové údaje, které kdy v repozitáři byly, byste proto měli vyměnit.

**Pomůže odstranit přístupové údaje dodatečně z historie Gitu?**  
Zabrání to tomu, aby je obsahovaly nové kopie. Kdo už repozitář stáhl, má staré stavy dál. Rozhodující je proto výměna přístupových údajů, ne jen přepsání historie.

**Týká se to i jiných systémů správy verzí?**  
Ano. I složky jako .svn nebo .hg obsahují data projektu a nikdy by neměly být dostupné ve webrootu. Obecné blokování souborů a složek s tečkou na začátku pokryje všechny tyto případy.

## Zdroje

- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)
- [Dokumentace Nginx](https://nginx.org/en/docs/)
- [Apache HTTP Server: dokumentace](https://httpd.apache.org/docs/)
