# Javni .git direktorij: podcijenjeno curenje podataka

> Je li Vaš .git direktorij javan? Kako to provjeriti, blokirati pristup, preurediti isporuku i postupati s pristupnim podacima iz povijesti.

Izvor: https://phpsos.de/hr/blog/git-ordner-oeffentlich/  
Stanje: 25.10.2026  
Pružatelj: PHP SOS, PHP hitna pomoć i sigurnost poslužitelja. Hitna pomoć putem WhatsAppa: https://wa.me/491736494914?text=Pozdrav%20PHP%20SOS%2C%20trebamo%20pomo%C4%87%20s%20na%C5%A1im%20PHP%20poslu%C5%BEiteljem.%20Tvrtka%3A%20%E2%80%A6%20Web-stranica%3A%20%E2%80%A6

**Ukratko:** Javni .git direktorij nastaje kad se web-stranica isporučuje pomoću `git clone` ili `git pull` izravno u webroot, a web-poslužitelj ne blokira skrivene direktorije. Tada se može dohvatiti cijeli izvorni kod zajedno s poviješću verzija, uključujući ranije unesene pristupne podatke. Svoje domene provjerite jednostavnim pozivom, odmah blokirajte pristup, isporuku prebacite na pakete bez `.git` i zamijenite pristupne podatke iz povijesti.

## Izvorni kod za ponijeti

Git je standardni alat za upravljanje verzijama, a malim je timovima prirodno da se njime i isporučuje: spojiti se na poslužitelj, `git pull`, gotovo. To radi pouzdano i brzo. Ima ipak nuspojavu koju često nitko ne primijeti.

U direktoriju projekta leži skriveni direktorij `.git`. On ne sadrži samo trenutačno stanje, nego svaku datoteku u svakoj verziji koja je ikada unesena, uz to poruke commitova, imena i adrese e-pošte razvojnih inženjera te reference na poslužitelje. Ako taj direktorij leži u webrootu i web-poslužitelj ga isporučuje, svatko ga može dohvatiti.

Za napadače je to dar. S izvornim kodom ranjivosti se mogu ciljano tražiti umjesto da ih se pogađa izvana. A u povijesti se često nalaze stvari koje su se činile davno obrisanima: lozinka baze podataka iz početnog razdoblja, API ključ, testna datoteka s podacima kupaca.

## Je li Vaš .git direktorij javan? Kako to provjeriti

Provjera traje sekunde i ništa ne mijenja. Za svaku domenu i poddomenu pozovite datoteku koja postoji u svakom Git repozitoriju:

```bash
# Očekuje se: 403 ili 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 poslužitelju: postoje li .git direktoriji ispod webroota?
find /var/www /srv/www -maxdepth 4 -type d -name ".git" 2>/dev/null
```

Status 200 znači: direktorij je dostupan. Obratite pažnju i na poddirektorije. Ponekad repozitorij ne leži u samom webrootu, nego u direktoriju dodatka ili teme koji se zasebno održava putem Gita.

Provjerite i staging i testna okruženja. Ona se putem Gita ažuriraju češće od produkcije i često su dostupna na poddomenama koje se mogu pogoditi.

## Odmah: blokirati pristup

Dok isporuka nije preuređena, pravilo u web-poslužitelju blokira pristup direktorijima sustava za verzioniranje. Opća blokada skrivenih datoteka, kako je opisano u članku [Ispravno zaštititi pristupne podatke i .env datoteke](https://phpsos.de/hr/blog/env-dateien-schuetzen/), to također pokriva. Tko želi ciljano blokirati samo sustav za verzioniranje, koristi uže pravilo:

```nginx
location ~ /\.(git|svn|hg)(/|$) {
    return 404;
}
```

```apache
RedirectMatch 404 /\.(git|svn|hg)(/|$)
```

Zatim ponovite gornju provjeru, i to pravim pozivom izvana: uspješan test konfiguracije govori samo da je sintaksa ispravna, a ne da pravilo djeluje prije drugih pravila za statične datoteke. Kod panela poput Plesk-a ili cPanela pravilo upišite u predviđene dodatne direktive, kako se ne bi izgubilo pri sljedećem generiranju konfiguracije.

> **Djelujte odmah:**
> Ako je direktorij bio dostupan, sve pristupne podatke koji su ikada bili u repozitoriju tretirajte kao poznate. Sama blokada tada nije dovoljna, vrijednosti se moraju zamijeniti.

## Trajno: isporučivati bez .git u webrootu

Blokada je zaštita, a ne rješenje. Trajno sustav za verzioniranje ne pripada na produkcijski poslužitelj. Dokazani putevi, ovisno o Vašem okruženju:

| Postupak | Kako radi | Prikladno za |
|---|---|---|
| Build paket iz CI-ja | pipeline gradi arhivu bez `.git`, poslužitelj je raspakira u novi direktorij izdanja | timovi s CI/CD-om |
| `git archive` | stvara arhivu stanja bez podataka o verzijama | mali projekti bez pipelinea |
| `rsync` s isključenjima | prenosi samo potrebne datoteke | klasični poslužitelji |
| Container image | kod se pri gradnji kopira u image, `.git` isključen pomoću `.dockerignore` | rad s containerima |

Direktorij izdanja po verziji sa simboličkom vezom na aktualno stanje ima još jednu prednost: pri problemima možete odmah vratiti staro. Za container postavke članak [CI/CD: automatski ponovno graditi PHP imageove](https://phpsos.de/hr/blog/php-images-in-ci-neu-bauen/) opisuje kako buildovi postaju ponovljivi. Tamo treba provjeriti i da `.git` ne dospije u image.

```bash
# Primjer: izraditi paket stanja bez podataka o verzijama
git archive --format=tar.gz -o release.tar.gz HEAD
```

## Daljnje datoteke projekta koje ne pripadaju u webroot

Direktorij `.git` najpoznatiji je primjer, ali ne i jedini. Tko isporučuje cijele direktorije projekta, u webroot donosi i druge datoteke koje tamo nemaju što tražiti:

- Direktoriji razvojnih okruženja poput `.idea` ili `.vscode`, u kojima proširenja za upload datoteka ponekad spremaju adrese poslužitelja i pristupne podatke.
- `composer.json` i `composer.lock`, koji otkrivaju točne verzije svih biblioteka i time olakšavaju potragu za poznatim ranjivostima.
- Konfiguracije za testove, alate za build i pipelineove, koje otkrivaju interne nazive hostova i postupke.
- Ostaci operacijskih sustava poput `.DS_Store`, koji sadrže popise datoteka cijelih direktorija.

Rješenje je isto kao kod direktorija `.git`: isporučivati samo ono što mora biti javno, idealno preko vlastitog poddirektorija kao webroota. Tko isporuku ionako prebacuje na pakete, odmah utvrđuje popis isključenih datoteka i provjerava ga uz svaki novi alat u projektu.

## Ako je direktorij bio otvoren: provjeriti povijest i zapisnike

Ako se pokaže da je direktorij `.git` bio dostupan, postupajte ovim redom:

1. **Blokirati pristup** i ponoviti provjeru.
2. **Pretražiti povijest** koje su tajne ikada unesene: konfiguracijske datoteke, `.env`, ključevi, dumpovi baza podataka.
3. **Zamijeniti pristupne podatke**, i to sve koje ste našli u koraku 2, čak i ako danas više nisu u kodu.
4. **Analizirati pristupne zapisnike** jesu li datoteke pod `/.git/` dohvaćane sa statusom 200 i s kojih adresa. Kako to ide, pokazuje [Analizirati zapisnike web-poslužitelja nakon napada](https://phpsos.de/hr/ratgeber/logfiles-auswerten/).
5. **Ciljano provjeriti izvorni kod**, jer ga napadači sada poznaju. Poznate slabosti treba prioritetno otkloniti.
6. **Razjasniti zaštitu podataka**, ako su u povijesti bili osobni podaci, primjerice testni izvozi. Procjenu preuzima Vaš službenik za zaštitu podataka.

Alati za traženje tajni u repozitorijima nakon toga trajno pripadaju u pipeline. OWASP takve provjere izričito preporučuje, kao hook prije unosa i u CI-ju.

## Kako PHP SOS konkretno pomaže?

- Provjeravamo sve Vaše domene i poddomene u potrazi za dostupnim direktorijima sustava za verzioniranje.
- Pristup blokiramo odmah i isporuku prebacujemo na pakete bez podataka o verzijama.
- Pretražujemo povijest u potrazi za tajnama i pratimo zamjenu pogođenih pristupa.
- Analiziramo pristupne zapisnike i dokumentiramo jesu li i kada podaci dohvaćani.

Ove mjere dio su našeg [ojačavanja poslužitelja za PHP web-poslužitelje](https://phpsos.de/hr/leistungen/server-haertung/).


## Česta pitanja

**Kako nastaje javni .git direktorij?**  
Najčešće isporukom putem git clone ili git pull izravno u webrootu. Direktorij .git s cijelom poviješću verzija tada leži pokraj index.php, a bez blokade web-poslužitelj isporučuje njegove datoteke.

**Je li dovoljno obrisati .git direktorij?**  
Za budućnost da, za prošlost ne. Ako je direktorij bio dostupan, sadržaj je možda već kopiran. Pristupne podatke koji su ikada bili u repozitoriju zato biste trebali zamijeniti.

**Pomaže li naknadno ukloniti pristupne podatke iz Git povijesti?**  
Sprječava da nove kopije sadrže te podatke. Tko je repozitorij već dohvatio, i dalje posjeduje stara stanja. Odlučujuća je stoga zamjena pristupnih podataka, a ne samo prepisivanje povijesti.

**Pogađa li to i druge sustave za verzioniranje?**  
Da. I direktoriji poput .svn ili .hg sadrže podatke projekta i nikad ne bi smjeli biti dostupni u webrootu. Opća blokada datoteka i direktorija s točkom na početku pokriva sve te slučajeve.

## Izvori

- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)
- [Nginx dokumentacija](https://nginx.org/en/docs/)
- [Apache HTTP Server: dokumentacija](https://httpd.apache.org/docs/)
