Co se stalo
FrankenPHP je moderní aplikační server pro PHP postavený na webovém serveru Caddy. Často se nasazuje jako hotový Docker obraz dunglas/frankenphp, například u aplikací na Symfony nebo Laravelu. Správci projektu 5. února 2026 zveřejnili na GitHubu bezpečnostní upozornění GHSA-x9p2-77v6-6vhf a označili ho jako kritické.
Problém není v samotném kódu FrankenPHP, ale ve způsobu, jakým se jeho Docker obrazy sestavovaly. Obrazy se přestavovaly jen tehdy, když vznikl nový tag základního obrazu. Alpine Linux, PHP a Go ale bezpečnostní opravy obvykle vydávají pod stávajícím tagem, takže obrazy FrankenPHP zůstávaly na starších, zranitelných knihovnách. Výrobce jako příklad uvádí chybu CVE-2025-15467 v knihovně libcrypto3, která umožňuje vzdálené spuštění kódu.
Společnost VulnCheck chybu 12. listopadu 2026 zaevidovala pod číslem CVE-2026-128027 a americká databáze NVD ji zveřejnila 13. listopadu 2026. Evropská databáze EUVD ji vede jako EUVD-2026-125075. Chyba není v katalogu CISA KEV, EUVD nezaznamenává její zneužití a výrobce o útocích nemluví. Chybu nahlásil a opravil Tim Nelles.
Proč je to nebezpečné
Jde o závislost na zranitelné komponentě třetí strany. VulnCheck ji označuje jako CWE-1395. Představte si stavební firmu, která do domů montuje zámky od dodavatele. Dodavatel vadný zámek potichu vymění za opravený, ale pod stejným katalogovým číslem. Firma sleduje jen číslo, a tak dál montuje staré zámky ze skladu. Přesně takhle se do obrazů FrankenPHP nedostaly opravy z Alpine, PHP a Go.
Podle VulnCheck mohli útočníci na dálku zneužít známé chyby v zastaralých systémových knihovnách a spustit na serveru vlastní kód. Výrobce je opatrnější: píše, že uživatelé mohli provozovat prostředí se známými zranitelnostmi, a to i tehdy, když měli nejnovější podobu svého tagu. V praxi zneužitelnost konkrétní chyby v knihovně závisí i na tom, jak ji aplikace používá.
Pokud by útok uspěl, útočník by ovládl kontejner s aplikací. Mohl by číst databázi, hesla a API klíče z proměnných prostředí, měnit web nebo se pokusit dostat k dalším systémům v síti. Zda by pronikl i na samotný hostitelský server, záleží na nastavení kontejneru.
Skóre CVSS vyjadřuje závažnost chyby na stupnici 0 až 10. VulnCheck, která CVE přidělila, uvádí podle CVSS 3.1 hodnotu 9,8, stejně jako upozornění FrankenPHP: útok vede přes síť, je jednoduchý a nevyžaduje přihlášení ani akci uživatele. Podle novější verze CVSS 4.0 ji VulnCheck hodnotí na 9,3. Skóre EPSS, které odhaduje pravděpodobnost zneužití v příštích 30 dnech, je 0,86 %, což je víc než u zhruba 59 % hodnocených chyb. Katalog CISA KEV, seznam prokazatelně zneužívaných chyb, ji neobsahuje.
Koho se to týká
Týká se to oficiálních Docker obrazů dunglas/frankenphp ve verzích před 1.1.11 a vlastních obrazů, které jsou na nich postavené, tedy těch, které mají v souboru Dockerfile řádek FROM dunglas/frankenphp. Výrobce upozorňuje, že ohrožen mohl být i ten, kdo používal nejnovější podobu konkrétního tagu.
Typicky jde o tato prostředí:
- firemní webové aplikace a e-shopy na PHP běžící v Dockeru nebo Kubernetes
- aplikace na Symfony nebo Laravelu nasazené v kontejnerech s FrankenPHP
- vývojové a testovací servery dostupné z internetu
- CI/CD pipeline, které z obrazu FrankenPHP staví vlastní obrazy
Netýká se to klasických instalací PHP s Apache nebo PHP-FPM bez FrankenPHP. Upozornění výrobce mluví o Docker obrazech, jiné způsoby instalace FrankenPHP v něm nezmiňuje.
Jak zjistit, zda jste zasaženi
Následující příkazy jen čtou informace a nic nemění. Nejprve zjistěte, které kontejnery běží z obrazu FrankenPHP:
docker ps --format '{{.Names}} {{.Image}}' | grep -i frankenphp
Vlastní obrazy mají vlastní název, takže je tento příkaz nenajde. Verzi FrankenPHP ve všech běžících kontejnerech vypíše:
docker ps --format '{{.Names}}' | while read c; do v=$(docker exec "$c" frankenphp version 2>/dev/null) && echo "$c: $v"; done
Verze nižší než 1.1.11 znamená, že jste zasaženi. U obrazů na Alpine zkontrolujte i verzi systému a knihovny libcrypto3. Místo nazev-kontejneru doplňte jméno kontejneru. Výrobce uvádí, že opravy přinesly Alpine 3.20.9, 3.21.6, 3.22.3 a 3.23.3. Nižší vydání ve stejné řadě je podezřelé.
docker exec nazev-kontejneru cat /etc/alpine-release
docker exec nazev-kontejneru apk list --installed libcrypto3
Obraz sestavený před 4. únorem 2026, kdy výrobce změnil způsob sestavování, mohl obsahovat staré knihovny. První příkaz vypíše datum sestavení všech obrazů na serveru. Druhý spusťte v adresáři s projekty, najde zmínky o FrankenPHP v souborech Dockerfile a Compose.
docker image ls --format '{{.Repository}}:{{.Tag}} {{.CreatedAt}}'
grep -rni frankenphp --include='Dockerfile*' --include='*compose*.yml' --include='*compose*.yaml' .
Jak to opravit
Opravená verze je 1.1.11. Od 4. února 2026 výrobce každý den porovnává základní obrazy se zdrojovými registry a při jakékoli změně obrazy FrankenPHP automaticky přestaví. K vám se ale oprava nedostane sama. Obraz je potřeba stáhnout znovu a kontejnery znovu vytvořit.
Postupujte takto:
- Sepište všechny servery, projekty a CI pipeline, které používají FrankenPHP.
- Pokud používáte tag starší než 1.1.11, změňte ho na 1.1.11 nebo novější.
- Stáhněte aktuální podobu svého tagu, například
docker pull dunglas/frankenphp:latest. - Pokud stavíte vlastní obraz, přestavte ho s přepínačem
--pull, aby Docker stáhl čerstvé základní vrstvy. - Kontejnery znovu vytvořte. Samotné stažení obrazu běžící kontejner nezmění.
- Příkazy z části o kontrole ověřte, že běží nová verze.
docker pull dunglas/frankenphp:latest
docker build --pull -t my-app .
U Docker Compose stačí v adresáři projektu:
docker compose pull --ignore-buildable
docker compose build --pull
docker compose up -d
Jako dočasné řešení výrobce uvádí právě vynucené stažení čerstvých základních vrstev přes --pull, jiná opatření nezmiňuje. Začněte systémy dostupnými z internetu, pak pokračujte interními a nakonec vývojovými prostředími.
Do budoucna nastavte pravidelné přestavování vlastních obrazů, například jednou týdně, a jejich kontrolu skenerem zranitelností, například Trivy nebo Grype. Zachytíte tak podobné problémy i v dalších obrazech.
Co když už jste mohli být napadeni
Výrobce ani VulnCheck nezveřejnili konkrétní indikátory napadení. Pokud zranitelný kontejner běžel delší dobu dostupný z internetu, udělejte základní kontrolu ještě před jeho zrušením, dokud jsou stopy na místě. Následující příkazy jen čtou:
- Logy zobrazí
docker logs nazev-kontejneru. Hledejte neobvyklé chyby, pády procesu a neznámé požadavky. - Příkaz
docker diff nazev-kontejneruukáže soubory, které přibyly nebo se změnily oproti obrazu. Podezřelé jsou nové PHP soubory ve webovém adresáři a spustitelné soubory v/tmp. - Příkaz
docker top nazev-kontejneruvypíše procesy. Kromě FrankenPHP a vaší aplikace by tam nemělo být nic. - V aplikaci a databázi hledejte neznámé administrátorské účty a nedávné změny oprávnění.
- Na firewallu zkontrolujte nečekaná odchozí spojení ze serveru.
Pokud najdete něco podezřelého, nestačí jen vyměnit kontejner. Změňte hesla k databázi, API klíče a další tajné údaje, ke kterým měl kontejner přístup. Přizvěte odborníka na bezpečnostní incidenty, zejména pokud měl kontejner připojený Docker socket nebo adresáře hostitele, případně běžel s rozšířenými oprávněními. Pak se útočník mohl dostat i na samotný server.