# Статичен анализ: PHPStan и Psalm

> PHPStan и Psalm, обяснени: нива на правилата, baseline, taint анализ и какво може и какво не може да направи статичният анализ за сигурни PHP приложения.

Източник: https://phpsos.de/bg/php/statische-analyse/  
Актуалност: 25.10.2026  
Доставчик: PHP SOS, Спешна помощ за PHP и сигурност на сървъри. Незабавна помощ по WhatsApp: https://wa.me/491736494914?text=%D0%97%D0%B4%D1%80%D0%B0%D0%B2%D0%B5%D0%B9%D1%82%D0%B5%2C%20PHP%20SOS%2C%20%D0%B8%D0%BC%D0%B0%D0%BC%D0%B5%20%D0%BD%D1%83%D0%B6%D0%B4%D0%B0%20%D0%BE%D1%82%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%20%D1%81%20%D0%BD%D0%B0%D1%88%D0%B8%D1%8F%20PHP%20%D1%81%D1%8A%D1%80%D0%B2%D1%8A%D1%80.%20%D0%A4%D0%B8%D1%80%D0%BC%D0%B0%3A%20%E2%80%A6%20%D0%A3%D0%B5%D0%B1%D1%81%D0%B0%D0%B9%D1%82%3A%20%E2%80%A6

**Накратко:** Статичният анализ проверява PHP код, без да го изпълнява, и така открива грешки в типовете, недефинирани променливи, мъртъв код и извиквания върху евентуално празни стойности. Двата разпространени инструмента са PHPStan (нива на правилата от 0 до 10) и Psalm (нива на грешките от 1 до 8, плюс taint анализ за несигурни потоци от данни). Те откриват грешки във Вашето приложение, не в интерпретатора на PHP; срещу уязвимости като PHP2Shell помага само актуализацията на PHP.

## Какво е статичен анализ?

Тестът изпълнява код и сравнява резултата. Статичният анализ, напротив, чете кода като много щателен проверяващ и от типовете, върнатите стойности и извикванията заключава къде нещо може да се обърка. Той открива грешки и в клонове, до които никой тест никога не стига.

За вземащите решения ползата е проста: грешките, открити преди пускането в продукция, струват дял от онези, които забелязват клиентите. За разработчиците той е постоянен спътник, който работи в средата за разработка и в CI конвейера. Ако анализът даде сигнал при дадена промяна, тя не се приема, докато грешката не бъде отстранена. Така не се натрупва нов стар багаж, докато наличният се намалява постепенно. Заедно с [тестовете с PHPUnit и Pest](https://phpsos.de/bg/php/php-testen/) той формира основата на качеството на кода.

## PHPStan: нива на правилата от 0 до 10

PHPStan се инсталира като зависимост за разработка и за да работи, изисква PHP от 7.4:

```bash
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse src tests
```

Без други указания PHPStan проверява само най-необходимото. Строгостта се управлява чрез единадесет нива, всяко включва по-ниските:

| Ниво | Какво се проверява допълнително (подбор) |
|---|---|
| 0 | непознати класове и функции, грешен брой аргументи, винаги недефинирани променливи |
| 3 | типове на върнатите стойности и типове, присвоявани на свойства |
| 5 | типове на аргументите при извикване на функции и методи |
| 6 | липсващи указания за типове |
| 8 | извиквания на методи и достъп до свойства върху стойности, които могат да са null |
| 10 | най-строго отношение към `mixed`, дори при липсващи типове |

С `--level max` винаги работи най-високото ниво. Документацията обаче предупреждава, че при такъв избор надграждането на PHPStan може да донесе много нови съобщения. Типична находка от ниво 8:

```php
<?php
function kundenname(?Kunde $kunde): string
{
    return $kunde->name();   // PHPStan: извикване върху стойност, която може да е null
}
```

## Въвеждане на PHPStan без наводнение от грешки: baseline

В изградени с времето проекти PHPStan на високо ниво често докладва стотици места. Baseline решава проблема: тя записва всички съществуващи съобщения във файл и оттам нататък PHPStan докладва само нови грешки.

```bash
vendor/bin/phpstan analyse --level 6 src tests --generate-baseline
```

Създаденият файл `phpstan-baseline.neon` се включва в конфигурацията:

```neon
includes:
    - phpstan-baseline.neon

parameters:
    level: 6
    paths:
        - src
        - tests
```

Така старият багаж остава видимо документиран, докато новият код трябва да е чист от самото начало.

## Psalm и taint анализът

Psalm преследва сходни цели с PHPStan. Нивата вървят обратно: 1 е най-строгото, 8 – най-снизходителното, по подразбиране е 2. Psalm изисква PHP от 8.2 и се настройва така:

```bash
composer require --dev vimeo/psalm
./vendor/bin/psalm --init
./vendor/bin/psalm --taint-analysis
```

Taint анализът е особено интересен за сигурността. „Taint“ означава зараза: Psalm отбелязва данни от източници, които атакуващият може да контролира, например `$_GET`, `$_POST`, `$_COOKIE`, `$_REQUEST` или `php://input`. След това проследява дали тези данни достигат незащитени опасни места, т.нар. sinks: извеждане с `echo`, `include`, `header` или SQL заявки. Към вградените категории спадат, наред с други, `sql`, `html`, `shell`, `include`, `eval`, `ssrf` и `unserialize`.

```php
<?php
// Psalm докладва поток от $_GET към HTML изхода (категория html)
echo 'Hallo ' . $_GET['name'];

// Отстранено: изходът се екранира според контекста
echo 'Hallo ' . htmlspecialchars($_GET['name'] ?? '', ENT_QUOTES, 'UTF-8');
```

Документацията на Psalm открито посочва границите: анализът приема, че екранирането е извършено правилно. Фини грешки, например липсващи кавички около HTML атрибут, въпреки това могат да оставят пробиви. Затова Psalm препоръчва параметризирани заявки за SQL и шаблони, съобразени с контекста, за HTML. Резултатите могат да се извеждат във формат SARIF, който разбира, наред с други, GitHub Code Scanning.

## Статичен анализ и сигурност след PHP2Shell

Тук си струва честно разграничаване. PHP2Shell, т.е. CVE-2026-109618 и CVE-2026-109619, се намира в интерпретатора на PHP. Никакъв инструмент, който чете кода на Вашето приложение, не открива тези уязвимости и никаква промяна в кода не ги затваря. Това постига само актуализацията до PHP 8.5.12, 8.4.27, 8.3.36 или 8.2.35.

Въпреки това статичният анализ допринася за сигурността на три места:

1. **Способност за надграждане:** Той открива код, който вече не работи в нови версии на PHP. Така спада прагът за преминаване от 8.1 или 8.2 към поддържана версия.
2. **Собствени пробиви:** Taint анализът открива пътища за [SQL инжекция](https://phpsos.de/bg/ratgeber/sql-injection-php/), cross-site scripting или включване на файлове. Проектът PHP изяснява в политиката си за сигурност, че непроверените входни данни към функции като `mysqli_query()` не са грешка на PHP, а са в отговорността на приложението.
3. **Устойчивост:** Много фатални грешки възникват от извиквания върху null или от грешни типове. php.net във връзка с CVE-2026-109619 изрично съветва фаталните грешки, които могат да бъдат предизвикани отвън, да се отстраняват в приложението.

Статичният анализ не замества [прегледа на кода от хора по отношение на сигурността](https://phpsos.de/bg/blog/sicherheits-code-review-php/), но го прави по-ефективен, защото рутинните грешки са отсеяни предварително.

## Как помага PHP SOS конкретно?

В рамките на [одит на сигурността и тест за проникване](https://phpsos.de/bg/leistungen/sicherheitsaudit-penetrationstest/) действаме така:

- **Настройване на инструментите:** PHPStan или Psalm с подходящо ниво и baseline, включени във Вашия съществуващ конвейер.
- **Оценка на находките за сигурността:** Проверяваме резултатите от taint анализа и отделяме истинските рискове от фалшивите аларми.
- **Подготовка на надграждането:** Показваме кои места блокират преминаването към поддържана версия на PHP.
- **Предаване на резултатите:** Получавате приоритизиран списък с конкретни места в кода за Вашия екип или Вашата агенция.


## Често задавани въпроси

**Каква е разликата между PHPStan и Psalm?**  
И двата проверяват типове и откриват грешки без изпълнение. PHPStan брои нивата си от 0 (свободно) до 10 (строго), Psalm – от 8 (свободно) до 1 (строго). Psalm носи вграден taint анализ за проблеми със сигурността.

**Мога ли да въведа PHPStan в стар проект?**  
Да. С baseline PHPStan записва всички съществуващи съобщения във файл и след това докладва само нови грешки. Така екипът започва без наводнение от грешки и намалява натрупаното постепенно.

**Открива ли статичният анализ PHP2Shell?**  
Не. PHP2Shell се намира в интерпретатора на PHP, а не във Вашия код. Срещу това помага само актуализацията на PHP. Статичният анализ обаче помага да се подготви кодът за нови версии на PHP, за да е възможна по-бързо актуализацията.

**Кое ниво да се избере?**  
За начало ниско ниво без baseline или по-високо ниво с baseline. По-важно от числото е анализът да се изпълнява автоматично при всяка промяна и да не пропуска нови грешки.

## Източници

- [PHPStan](https://phpstan.org/)
- [Psalm](https://psalm.dev/)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
