Kort sagt: Statisk analys kontrollerar PHP-kod utan att köra den och hittar på så sätt typfel, odefinierade variabler, död kod och anrop på möjligen tomma värden. De två utbredda verktygen är PHPStan (regelnivåer 0 till 10) och Psalm (felnivåer 1 till 8, dessutom en taint-analys för osäkra dataflöden). De hittar fel i er applikation, inte i PHP-tolken; mot luckor som PHP2Shell hjälper bara PHP-uppdateringen.
Vad är statisk analys?
Ett test kör kod och jämför resultatet. Statisk analys läser i stället koden som en mycket grundlig granskare och drar av typer, returvärden och anrop slutsatser om var något kan gå snett. Den hittar fel även i grenar som inget test någonsin når.
För beslutsfattare är nyttan enkel: Fel som hittas före driftstart kostar en bråkdel av fel som kunderna märker. För utvecklare är den en ständig följeslagare som körs i utvecklingsmiljön och i CI-pipelinen. Slår analysen larm vid en ändring godkänns inte ändringen förrän felet är åtgärdat. Så växer inget nytt gammalt bestånd till, medan det befintliga stegvis byggs bort. Tillsammans med tester med PHPUnit och Pest utgör den grunden för kodkvaliteten.
PHPStan: regelnivåer från 0 till 10
PHPStan installeras som utvecklingsberoende och kräver PHP från 7.4 för att köra:
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse src tests
Utan ytterligare angivelse kontrollerar PHPStan bara det nödvändigaste. Strängheten styr ni med elva nivåer, där varje nivå omfattar de underliggande:
| Nivå | Vad som kontrolleras dessutom (urval) |
|---|---|
| 0 | okända klasser och funktioner, fel antal argument, alltid odefinierade variabler |
| 3 | returtyper och typer som tilldelas egenskaper |
| 5 | typer på argumenten vid funktions- och metodanrop |
| 6 | saknade typangivelser |
| 8 | metodanrop och egenskapsåtkomst på värden som kan vara null |
| 10 | strängaste hanteringen av mixed, även vid saknade typer |
Med --level max körs alltid den högsta nivån. Dokumentationen varnar dock för att en uppgradering av PHPStan då kan ge många nya meddelanden. Ett typiskt fynd från nivå 8:
<?php
function kundenname(?Kunde $kunde): string
{
return $kunde->name(); // PHPStan: anrop på ett värde som kan vara null
}
Införa PHPStan utan felflod: baseline
I projekt som vuxit fram rapporterar PHPStan på hög nivå ofta hundratals ställen. Baseline löser problemet: Den sparar alla befintliga meddelanden i en fil, och PHPStan rapporterar därefter bara nya fel.
vendor/bin/phpstan analyse --level 6 src tests --generate-baseline
Den skapade filen phpstan-baseline.neon binder ni in i konfigurationen:
includes:
- phpstan-baseline.neon
parameters:
level: 6
paths:
- src
- tests
Så förblir det gamla beståndet synligt dokumenterat, medan ny kod måste vara ren från början.
Psalm och taint-analysen
Psalm har liknande mål som PHPStan. Nivåerna går omvänt: 1 är den strängaste, 8 den mildaste, standard är 2. Psalm kräver PHP från 8.2 och sätts upp så här:
composer require --dev vimeo/psalm
./vendor/bin/psalm --init
./vendor/bin/psalm --taint-analysis
Taint-analysen är särskilt intressant för säkerheten. ”Taint” betyder nedsmutsning: Psalm markerar data från källor som en angripare kan kontrollera, till exempel $_GET, $_POST, $_COOKIE, $_REQUEST eller php://input. Sedan följer den om de här uppgifterna oskyddade når farliga ställen, de så kallade sänkorna: utskrift med echo, include, header eller SQL-frågor. Till de inbyggda kategorierna hör bland annat sql, html, shell, include, eval, ssrf och unserialize.
<?php
// Psalm rapporterar ett flöde från $_GET till HTML-utskriften (kategori html)
echo 'Hallo ' . $_GET['name'];
// Åtgärdat: maskera utskriften för rätt kontext
echo 'Hallo ' . htmlspecialchars($_GET['name'] ?? '', ENT_QUOTES, 'UTF-8');
Psalms dokumentation nämner gränserna öppet: Analysen utgår från att maskeringen sker korrekt. Små fel, till exempel saknade citattecken kring ett HTML-attribut, kan ändå lämna luckor. Psalm rekommenderar därför parametriserade frågor för SQL och kontextmedvetna mallar för HTML. Resultat kan matas ut i SARIF-formatet, som bland annat GitHub Code Scanning förstår.
Statisk analys och säkerhet efter PHP2Shell
Här är en ärlig avgränsning på sin plats. PHP2Shell, alltså CVE-2026-109618 och CVE-2026-109619, sitter i PHP-tolken. Inget verktyg som läser er applikationskod hittar de här luckorna, och ingen kodändring stänger dem. Det klarar bara uppdateringen till PHP 8.5.12, 8.4.27, 8.3.36 eller 8.2.35.
Ändå bidrar statisk analys till säkerheten, på tre ställen:
- Uppgraderingsförmåga: Den hittar kod som inte längre körs på nya PHP-versioner. Därmed sjunker tröskeln att byta från 8.1 eller 8.2 till en version som stöds.
- Egna luckor: Taint-analysen hittar vägar för SQL-injektion, cross-site scripting eller filinkludering. PHP-projektet klargör i sin säkerhetspolicy att ogranskad indata till funktioner som
mysqli_query()inte är ett fel i PHP utan ligger på applikationens ansvar. - Robusthet: Många fatala fel uppstår genom anrop på null eller fel typer. php.net råder i samband med CVE-2026-109619 uttryckligen att åtgärda fatala fel i applikationen som kan utlösas utifrån.
Statisk analys ersätter ingen säkerhetsgranskning av koden av människor, men den gör den effektivare, eftersom rutinfel är bortsorterade i förväg.
Hur hjälper PHP SOS konkret?
Inom ramen för säkerhetsgranskning och penetrationstest går vi tillväga så här:
- Ställa in verktyg: PHPStan eller Psalm med lämplig nivå och baseline, inkopplade i er befintliga pipeline.
- Bedöma säkerhetsfynd: Vi granskar resultaten av taint-analysen och skiljer verkliga risker från falsklarm.
- Förbereda uppgradering: Vi visar vilka ställen som blockerar ett byte till en PHP-version som stöds.
- Lämna över resultat: Ni får en prioriterad lista med konkreta kodställen för ert team eller er byrå.
Vanliga frågor
Vad är skillnaden mellan PHPStan och Psalm?
Båda kontrollerar typer och hittar fel utan körning. PHPStan räknar sina nivåer från 0 (lös) till 10 (sträng), Psalm från 8 (lös) till 1 (sträng). Psalm har en inbyggd taint-analys för säkerhetsproblem.
Kan jag införa PHPStan i ett gammalt projekt?
Ja. Med en baseline sparar PHPStan alla befintliga meddelanden i en fil och rapporterar därefter bara nya fel. Så startar teamet utan en flod av fel och bygger stegvis bort gamla laster.
Hittar statisk analys PHP2Shell?
Nej. PHP2Shell sitter i PHP-tolken, inte i er kod. Mot det hjälper bara PHP-uppdateringen. Statisk analys hjälper däremot att förbereda koden för nya PHP-versioner, så att uppdateringen går snabbare.
Vilken nivå ska man välja?
För att komma igång en låg nivå utan baseline eller en högre nivå med baseline. Viktigare än siffran är att analysen körs automatiskt vid varje ändring och inte släpper igenom nya fel.