# Statička analiza: PHPStan i Psalm

> PHPStan i Psalm objašnjeni: razine pravila, baseline, taint analiza i što statička analiza može, a što ne može učiniti za sigurne PHP aplikacije.

Izvor: https://phpsos.de/hr/php/statische-analyse/  
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:** Statička analiza provjerava PHP kod bez njegova izvršavanja i tako pronalazi pogreške tipova, nedefinirane varijable, mrtvi kod i pozive na vrijednostima koje bi mogle biti prazne. Dva raširena alata su PHPStan (razine pravila od 0 do 10) i Psalm (razine pogrešaka od 1 do 8, uz taint analizu za nesigurne tokove podataka). Pronalaze pogreške u Vašoj aplikaciji, a ne u PHP interpreteru; protiv ranjivosti poput PHP2Shella pomaže samo PHP ažuriranje.

## Što je statička analiza?

Test izvršava kod i uspoređuje rezultat. Statička analiza, naprotiv, čita kod poput vrlo temeljitog recenzenta i iz tipova, povratnih vrijednosti i poziva zaključuje gdje nešto može poći po zlu. Pogreške pronalazi i u granama do kojih nijedan test nikad ne dođe.

Za donositelje odluka korist je jednostavna: pogreške pronađene prije puštanja uživo koštaju djelić onoga što koštaju pogreške koje primijete kupci. Za programere je to stalni pratitelj koji radi uz razvojno okruženje i u CI pipelineu. Ako analiza pri promjeni zazvoni, ta se promjena ne preuzima dok se pogreška ne otkloni. Tako ne raste novo naslijeđe, a postojeće se postupno smanjuje. Zajedno s [testovima s PHPUnitom i Pestom](https://phpsos.de/hr/php/php-testen/) čini temelj kvalitete koda.

## PHPStan: razine pravila od 0 do 10

PHPStan se instalira kao razvojna ovisnost i za rad zahtijeva PHP od 7.4:

```bash
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse src tests
```

Bez dodatnih oznaka PHPStan provjerava samo najnužnije. Strogoću kontrolirate kroz jedanaest razina, a svaka uključuje one ispod sebe:

| Razina | Što se dodatno provjerava (izbor) |
|---|---|
| 0 | nepoznate klase i funkcije, pogrešan broj argumenata, uvijek nedefinirane varijable |
| 3 | povratni tipovi i tipovi koji se dodjeljuju svojstvima |
| 5 | tipovi argumenata pri pozivima funkcija i metoda |
| 6 | nedostajuće oznake tipova |
| 8 | pozivi metoda i pristupi svojstvima na vrijednostima koje mogu biti null |
| 10 | najstrože postupanje s `mixed`, i kod nedostajućih tipova |

S `--level max` uvijek se izvršava najviša razina. Dokumentacija ipak upozorava da nadogradnja PHPStana tada može donijeti mnogo novih poruka. Tipičan nalaz od razine 8:

```php
<?php
function kundenname(?Kunde $kunde): string
{
    return $kunde->name();   // PHPStan: poziv na vrijednosti koja može biti null
}
```

## Uvođenje PHPStana bez poplave pogrešaka: baseline

U razvijenim projektima PHPStan na visokoj razini često prijavljuje stotine mjesta. Baseline rješava problem: sprema sve postojeće poruke u datoteku, a PHPStan od tada prijavljuje samo nove pogreške.

```bash
vendor/bin/phpstan analyse --level 6 src tests --generate-baseline
```

Stvorenu datoteku `phpstan-baseline.neon` uključujete u konfiguraciju:

```neon
includes:
    - phpstan-baseline.neon

parameters:
    level: 6
    paths:
        - src
        - tests
```

Tako naslijeđe ostaje vidljivo dokumentirano, dok novi kod od početka mora biti čist.

## Psalm i taint analiza

Psalm ima slične ciljeve kao PHPStan. Razine idu obrnuto: 1 je najstroža, 8 najblaža, a zadana je 2. Psalm zahtijeva PHP od 8.2 i postavlja se ovako:

```bash
composer require --dev vimeo/psalm
./vendor/bin/psalm --init
./vendor/bin/psalm --taint-analysis
```

Taint analiza osobito je zanimljiva za sigurnost. „Taint“ znači onečišćenje: Psalm označava podatke iz izvora koje napadač može kontrolirati, primjerice `$_GET`, `$_POST`, `$_COOKIE`, `$_REQUEST` ili `php://input`. Zatim prati stižu li ti podaci nezaštićeni na opasna mjesta, takozvane sinkove: ispis s `echo`, `include`, `header` ili SQL upite. Među ugrađene kategorije, među ostalim, spadaju `sql`, `html`, `shell`, `include`, `eval`, `ssrf` i `unserialize`.

```php
<?php
// Psalm prijavljuje tok iz $_GET u HTML izlaz (kategorija html)
echo 'Hallo ' . $_GET['name'];

// Otklonjeno: izlaz maskirati prema kontekstu
echo 'Hallo ' . htmlspecialchars($_GET['name'] ?? '', ENT_QUOTES, 'UTF-8');
```

Psalmova dokumentacija otvoreno navodi granice: analiza pretpostavlja da se maskiranje provodi ispravno. Fine pogreške, primjerice nedostajući navodnici oko HTML atributa, ipak mogu ostaviti ranjivosti. Psalm zato preporučuje parametrizirane upite za SQL i predloške svjesne konteksta za HTML. Rezultati se mogu ispisati u SARIF formatu, koji, među ostalim, razumije GitHub Code Scanning.

## Statička analiza i sigurnost nakon PHP2Shella

Ovdje vrijedi iskreno razgraničenje. PHP2Shell, dakle CVE-2026-109618 i CVE-2026-109619, nalazi se u PHP interpreteru. Nijedan alat koji čita kod Vaše aplikacije ne pronalazi te ranjivosti i nijedna promjena koda ne zatvara ih. To postiže samo ažuriranje na PHP 8.5.12, 8.4.27, 8.3.36 ili 8.2.35.

Ipak, statička analiza pridonosi sigurnosti na tri mjesta:

1. **Sposobnost nadogradnje:** Pronalazi kod koji na novim verzijama PHP-a više ne radi. Time pada prepreka prijelazu s 8.1 ili 8.2 na podržanu verziju.
2. **Vlastite ranjivosti:** Taint analiza pronalazi putove za [SQL injection](https://phpsos.de/hr/ratgeber/sql-injection-php/), cross-site scripting ili uključivanje datoteka. PHP projekt u svojim sigurnosnim smjernicama pojašnjava da neprovjereni unosi u funkcije poput `mysqli_query()` nisu pogreška PHP-a, nego su u odgovornosti aplikacije.
3. **Otpornost:** Mnoge fatalne pogreške nastaju pozivima na null ili pogrešnim tipovima. U vezi s CVE-2026-109619 php.net izričito savjetuje da se u aplikaciji otklone izvana izazvane fatalne pogreške.

Statička analiza ne zamjenjuje [sigurnosnu reviziju koda](https://phpsos.de/hr/blog/sicherheits-code-review-php/) koju provode ljudi, ali je čini učinkovitijom jer su rutinske pogreške prethodno izdvojene.

## Kako PHP SOS konkretno pomaže?

U okviru [sigurnosnog audita i penetracijskog testa](https://phpsos.de/hr/leistungen/sicherheitsaudit-penetrationstest/) postupamo ovako:

- **Postaviti alate:** PHPStan ili Psalm s odgovarajućom razinom i baselineom, uključen u Vaš postojeći pipeline.
- **Procijeniti sigurnosne nalaze:** Provjeravamo rezultate taint analize i razdvajamo stvarne rizike od lažnih uzbuna.
- **Pripremiti nadogradnju:** Pokazujemo koja mjesta blokiraju prijelaz na podržanu verziju PHP-a.
- **Predati rezultate:** Dobivate prioritiziran popis s konkretnim mjestima u kodu za Vaš tim ili agenciju.


## Česta pitanja

**Koja je razlika između PHPStana i Psalma?**  
Oba provjeravaju tipove i pronalaze pogreške bez izvršavanja. PHPStan svoje razine broji od 0 (blago) do 10 (strogo), Psalm od 8 (blago) do 1 (strogo). Psalm donosi ugrađenu taint analizu za sigurnosne probleme.

**Mogu li PHPStan uvesti u stari projekt?**  
Da. S baselineom PHPStan sve postojeće poruke sprema u datoteku i nakon toga prijavljuje samo nove pogreške. Tako tim počinje bez poplave pogrešaka i postupno otklanja naslijeđe.

**Pronalazi li statička analiza PHP2Shell?**  
Ne. PHP2Shell je u PHP interpreteru, a ne u Vašem kodu. Protiv njega pomaže samo PHP ažuriranje. Statička analiza ipak pomaže pripremiti kod za nove verzije PHP-a, pa ažuriranje bude brže moguće.

**Koju razinu odabrati?**  
Za početak nisku razinu bez baselinea ili višu razinu s baselineom. Važnije od broja je da se analiza automatski izvršava pri svakoj promjeni i ne propušta nove pogreške.

## Izvori

- [PHPStan](https://phpstan.org/)
- [Psalm](https://psalm.dev/)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
