# display_errors off: isključiti ispis pogrešaka u produkciji

> display_errors Off i više: koje PHP postavke drže poruke o pogreškama podalje od žive web-stranice, što dodaju frameworki i kako provjeriti curenje informacija.

Izvor: https://phpsos.de/hr/blog/display-errors-produktion/  
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:** Na živoj web-stranici `display_errors = Off` pripada u php.ini, zajedno s `display_startup_errors = Off`, `log_errors = On` i zapisnikom pogrešaka izvan web-korijena. Uz to CMS-ovi i frameworki moraju raditi u produkcijskom načinu, inače njihove vlastite stranice s pogreškama prikazuju pojedinosti. Zaključane pomoću `php_admin_flag` i provjeravane nakon svakog ažuriranja, pogreške ostaju u zapisniku umjesto u pregledniku.

## Što odaje jedna jedina poruka o pogrešci

Upozorenje na vrhu stranice, „Fatal error“ umjesto pregleda narudžbe: takvi ispisi izgledaju bezazleno. Za napadača su karta. Pokazuju potpune putove datoteka, nazive baza podataka i tablica, korištene biblioteke i često verziju PHP-a.

Osobito u situacijama poput PHP2Shella, u kojima se masovno traže ranjivi poslužitelji, poslužitelj bi trebao odavati što je moguće manje o sebi. To ne zatvara ranjivost u PHP interpreteru, ali otežava svaki daljnji korak nakon provale i čini ciljane napade na Vašu aplikaciju mukotrpnijima.

Tu je i zaštita podataka. Poruke o pogreškama mogu sadržavati dijelove zahtjeva, primjerice e-adrese iz obrazaca. Što se pojavi u pregledniku posjetitelja, više nije pod Vašom kontrolom.

## Zadane vrijednosti nisu zamišljene za produkciju

Mnogi pretpostavljaju da PHP pogreške sam skriva. PHP priručnik kaže drugo: ugrađena zadana vrijednost `display_errors` je 1, a `display_startup_errors` je od PHP-a 8.0 također zadano uključen. Tek isporučeni predložak `php.ini-production` postavlja oboje na Off. Priručnik `display_errors` izričito naziva razvojnom funkcijom koju nikada ne treba koristiti na sustavima na internetu.

Koristi li Vaš poslužitelj produkcijski predložak, nije samorazumljivo. Image-i kontejnera katkad se pokreću posve bez php.ini, hosting paneli postavljaju vlastite vrijednosti, a nakon selidbe rado se kopira razvojni predložak.

## display_errors off: pregled postavki

Sljedeće vrijednosti smislene su za produkcijske poslužitelje. Konstante poput `E_ALL` rade samo u php.ini; u Apache konfiguraciji prema PHP priručniku nemaju značenje i moraju se navesti kao broj.

| Postavka | Produkcija | Svrha |
|---|---|---|
| `display_errors` | `Off` | nema pogrešaka u pregledniku |
| `display_startup_errors` | `Off` | nema pogrešaka pri pokretanju PHP-a u izlazu |
| `log_errors` | `On` | pogreške upisivati u zapisnik |
| `error_log` | putanja izvan web-korijena | zasebna zapisnička datoteka po web-stranici ili poolu |
| `error_reporting` | `E_ALL` | zapisivati sve pogreške, ne prikazivati |
| `html_errors` | `Off` | običan tekst umjesto HTML-a u zapisnicima |
| `zend.exception_ignore_args` | `On` | bez argumenata funkcija u stack traceovima |
| `fatal_error_backtraces` | `0` do ažuriranja (samo PHP 8.5) | prijelazna mjera prema php.net-u |

`zend.exception_ignore_args` osobito je vrijedan. Bez te postavke stack traceovi u zapisnicima i na stranicama s pogreškama mogu sadržavati argumente poziva funkcija, dakle i lozinke ili tokene koji su upravo obrađivani.

```ini
; php.ini web SAPI-ja
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/website-fehler.log
error_reporting = E_ALL
html_errors = Off
zend.exception_ignore_args = On
; samo PHP 8.5, prijelazna mjera do ažuriranja na 8.5.12:
; fatal_error_backtraces = 0
```

U FPM poolu najvažnije vrijednosti dodatno zaključajte kako ih nijedna aplikacija ne bi putem `ini_set()` ponovno uključila:

```ini
; npr. /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_flag[display_errors] = off
php_admin_flag[display_startup_errors] = off
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php/seite1-fehler.log
```

Zatim ponovno pokrenite dotičnu PHP uslugu. Kako zaključavanje točno funkcionira, objašnjava članak [php_admin_value: zaključati postavke od nadjačavanja](https://phpsos.de/hr/blog/php-admin-value-sperren/). Potpunu osnovnu konfiguraciju naći ćete u članku [Sigurno konfigurirati php.ini](https://phpsos.de/hr/ratgeber/php-ini-sicher-konfigurieren/).

## Druga sklopka: debug način aplikacije

PHP je tek pola posla. Moderni frameworki sami hvataju pogreške i prikazuju vlastite, često vrlo opširne stranice s pogreškama. U debug načinu sadrže izvatke izvornog koda, konfiguracijske vrijednosti i ponekad varijable okruženja. Te se stranice pojavljuju čak i kad je `display_errors` u PHP-u isključen.

Zato za svaku aplikaciju provjerite njezinu vlastitu sklopku. Kod WordPressa to su `WP_DEBUG` i `WP_DEBUG_DISPLAY` u `wp-config.php`, kod Laravela i Symfonyja `APP_DEBUG` i okruženje u datoteci `.env`, kod drugih sustava produkcijski način prema dokumentaciji proizvođača. Na živom sustavu debug način trajno pripada isključen, a i „samo načas za testiranje“ je rizik.

Kako se pogreške u aplikaciji uredno obrađuju umjesto da se potiskuju, opisuje članak [Pogreške i iznimke u PHP-u](https://phpsos.de/hr/php/fehler-und-exceptions/).

## Kako pronaći ispise pogrešaka prije nego ih nađu drugi

Jednokratno postavljanje nije dovoljno. Ispisi pogrešaka vraćaju se nakon ažuriranja, selidbi ili izmjena u panelu. Pomaže kratak postupak provjere:

1. Provjeriti djelotvorne vrijednosti u web-kontekstu, a ne samo u naredbenom retku, primjerice kratko odloženom datotekom za provjeru koja se odmah zatim briše.
2. Provjeriti debug način svake aplikacije u njezinoj konfiguracijskoj datoteci.
3. Isporučene stranice pretražiti na tipične tekstove pogrešaka, kao u bloku koda ispod.
4. U tražilici upitom `site:` na Vašu domenu tražiti pojmove poput „Fatal error“ ili „Warning“.
5. Provjeriti upisuje li se u zapisnik pogrešaka i da se ne nalazi u web-korijenu.

```bash
# Pretražiti isporučene stranice na tekstove PHP pogrešaka (samo vlastite domene)
for url in https://www.example.de/ https://www.example.de/kontakt/; do
  curl -s "$url" | grep -E -o "(Fatal error|Warning|Notice|Deprecated|Stack trace)[^<]{0,80}" | head -3
done
# Upisuje li se u zapisnik pogrešaka?
ls -l /var/log/php/
```

> **Važno:**
> Skrivanje pogrešaka nije zamjena za njihovo otklanjanje. Zapisnik pun upozorenja znak je potrebe za održavanjem, a nakon provale često je važan trag. Što pritom zapisivati, a što ne, opisuje članak [Sigurno zapisivati: bilježiti pogreške bez curenja podataka](https://phpsos.de/hr/blog/sicher-loggen-php/).

## Zaključak: tiho u pregledniku, govorljivo u zapisniku

Pravilo za produkcijske poslužitelje je jednostavno: pogreške pripadaju u zapisnik, a ne na web-stranicu. U praksi ga ometaju zadane vrijednosti koje nisu zamišljene za produkciju, debug sklopke u aplikacijama i konfiguracije koje se nakon ažuriranja ili selidbi vrate unatrag.

Tko isključi `display_errors` i `display_startup_errors`, zaključa vrijednosti u poolu, provjeri debug način aplikacije i redovito provjerava rezultat, zatvara jedan od najčešćih izvora nepotrebnog odavanja informacija. Trud je malen, a učinak traje dok provjera ostaje dio svakog ažuriranja.

Jednu točku ne treba previdjeti: zapisnik pogrešaka nije kanta za smeće. Tko ga redovito čita, prepoznaje pogrešna ažuriranja, zastarjele funkcije, a ponekad i prve tragove napada, dugo prije nego što kupci išta primijete.

## Kako PHP SOS konkretno pomaže?

- **Provjeriti:** očitavamo djelotvorne postavke pogrešaka po web-stranici i poolu te pretražujemo isporučene stranice na ispise pogrešaka.
- **Prebaciti:** PHP i postavke aplikacije postavljamo za produkcijski rad i zaključavamo ih od nadjačavanja.
- **Postaviti zapisnike:** zapisnici pogrešaka nalaze se izvan web-korijena, rotiraju se i dostupni su Vašim programerima.
- **Zadržati trajno:** u [sigurnosnom ugovoru o održavanju](https://phpsos.de/hr/leistungen/security-wartungsvertrag/) postavke ponovno provjeravamo nakon svakog ažuriranja.


## Česta pitanja

**Nije li display_errors u PHP-u ionako isključen?**  
Nije automatski. Prema PHP priručniku ugrađena zadana vrijednost display_errors je 1. Tek isporučeni predložak php.ini-production postavlja Off. Koristi li Vaš poslužitelj taj predložak, ovisi o distribuciji, panelu ili image-u kontejnera i treba provjeriti.

**Je li display_errors = Off dovoljan ako WordPress ili Laravel rade u debug načinu?**  
Nije. Mnogi CMS-ovi i frameworki donose vlastite stranice s pogreškama koje neovisno o PHP-u mogu prikazivati pojedinosti. Zato isključite i debug način aplikacije, primjerice WP_DEBUG_DISPLAY kod WordPressa ili APP_DEBUG kod Laravela i Symfonyja.

**Kamo idu pogreške kad se više ne prikazuju?**  
Uz log_errors = On PHP ih upisuje u datoteku koju navodi error_log ili u zapisnik dotičnog načina rada, primjerice zapisnik pogrešaka Apachea ili PHP-FPM-a. Datoteka bi trebala biti izvan web-korijena i redovito se rotirati.

**Kakve veze fatal_error_backtraces ima s PHP2Shellom?**  
Postavka postoji od PHP-a 8.5 i zadano je aktivna. php.net navodi fatal_error_backtraces=0 s naknadnim ponovnim pokretanjem kao jednu od prijelaznih mjera za PHP 8.5 dok ažuriranje na 8.5.12 još nije provedeno. Ne zamjenjuje ažuriranje.

## Izvori

- [PHP priručnik: obrada pogrešaka i zapisivanje](https://www.php.net/manual/en/errorfunc.configuration.php)
- [PHP priručnik: mijenjanje konfiguracije (php_admin_flag)](https://www.php.net/manual/en/configuration.changes.php)
- [php.net: sigurnosne obavijesti](https://www.php.net/)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
