Накратко: Статичният анализ проверява PHP код, без да го изпълнява, и така открива грешки в типовете, недефинирани променливи, мъртъв код и извиквания върху евентуално празни стойности. Двата разпространени инструмента са PHPStan (нива на правилата от 0 до 10) и Psalm (нива на грешките от 1 до 8, плюс taint анализ за несигурни потоци от данни). Те откриват грешки във Вашето приложение, не в интерпретатора на PHP; срещу уязвимости като PHP2Shell помага само актуализацията на PHP.
Какво е статичен анализ?
Тестът изпълнява код и сравнява резултата. Статичният анализ, напротив, чете кода като много щателен проверяващ и от типовете, върнатите стойности и извикванията заключава къде нещо може да се обърка. Той открива грешки и в клонове, до които никой тест никога не стига.
За вземащите решения ползата е проста: грешките, открити преди пускането в продукция, струват дял от онези, които забелязват клиентите. За разработчиците той е постоянен спътник, който работи в средата за разработка и в CI конвейера. Ако анализът даде сигнал при дадена промяна, тя не се приема, докато грешката не бъде отстранена. Така не се натрупва нов стар багаж, докато наличният се намалява постепенно. Заедно с тестовете с PHPUnit и Pest той формира основата на качеството на кода.
PHPStan: нива на правилата от 0 до 10
PHPStan се инсталира като зависимост за разработка и за да работи, изисква PHP от 7.4:
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
function kundenname(?Kunde $kunde): string
{
return $kunde->name(); // PHPStan: извикване върху стойност, която може да е null
}
Въвеждане на PHPStan без наводнение от грешки: baseline
В изградени с времето проекти PHPStan на високо ниво често докладва стотици места. Baseline решава проблема: тя записва всички съществуващи съобщения във файл и оттам нататък PHPStan докладва само нови грешки.
vendor/bin/phpstan analyse --level 6 src tests --generate-baseline
Създаденият файл phpstan-baseline.neon се включва в конфигурацията:
includes:
- phpstan-baseline.neon
parameters:
level: 6
paths:
- src
- tests
Така старият багаж остава видимо документиран, докато новият код трябва да е чист от самото начало.
Psalm и taint анализът
Psalm преследва сходни цели с PHPStan. Нивата вървят обратно: 1 е най-строгото, 8 – най-снизходителното, по подразбиране е 2. Psalm изисква PHP от 8.2 и се настройва така:
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
// 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.
Въпреки това статичният анализ допринася за сигурността на три места:
- Способност за надграждане: Той открива код, който вече не работи в нови версии на PHP. Така спада прагът за преминаване от 8.1 или 8.2 към поддържана версия.
- Собствени пробиви: Taint анализът открива пътища за SQL инжекция, cross-site scripting или включване на файлове. Проектът PHP изяснява в политиката си за сигурност, че непроверените входни данни към функции като
mysqli_query()не са грешка на PHP, а са в отговорността на приложението. - Устойчивост: Много фатални грешки възникват от извиквания върху null или от грешни типове. php.net във връзка с CVE-2026-109619 изрично съветва фаталните грешки, които могат да бъдат предизвикани отвън, да се отстраняват в приложението.
Статичният анализ не замества прегледа на кода от хора по отношение на сигурността, но го прави по-ефективен, защото рутинните грешки са отсеяни предварително.
Как помага PHP SOS конкретно?
В рамките на одит на сигурността и тест за проникване действаме така:
- Настройване на инструментите: 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. По-важно от числото е анализът да се изпълнява автоматично при всяка промяна и да не пропуска нови грешки.