Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

Статичен анализ: PHPStan и Psalm

PHPStan и Psalm откриват грешки в PHP кода, без да го изпълняват. Psalm допълнително проследява несигурните потоци от данни. Уязвимости в самия интерпретатор на PHP и двата не откриват.

Актуалност 5 мин. четенеЗнания за PHP

Накратко: Статичният анализ проверява 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.

Въпреки това статичният анализ допринася за сигурността на три места:

  1. Способност за надграждане: Той открива код, който вече не работи в нови версии на PHP. Така спада прагът за преминаване от 8.1 или 8.2 към поддържана версия.
  2. Собствени пробиви: Taint анализът открива пътища за SQL инжекция, cross-site scripting или включване на файлове. Проектът PHP изяснява в политиката си за сигурност, че непроверените входни данни към функции като mysqli_query() не са грешка на PHP, а са в отговорността на приложението.
  3. Устойчивост: Много фатални грешки възникват от извиквания върху 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. По-важно от числото е анализът да се изпълнява автоматично при всяка промяна и да не пропуска нови грешки.

Източници

Незабавен контакт

Всеки час има значение. Пишете ни сега.

Опишете накратко системата, версията на PHP и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ