Releases: php/frankenphp
Release list
v1.12.6
FrankenPHP 1.12.6 fixes a crash that could take down the whole process on HTTP/2. If a PHP script calls frankenphp_finish_request() (or closes its context early) and then lazily reads php://input — common with enable_post_data_reading=Off — FrankenPHP set a read deadline on an already-finalized HTTP/2 stream and segfaulted. HTTP/1 was unaffected. Anyone serving over HTTP/2 should upgrade.
🐛 Bug Fixes
- HTTP/2: Don't set a request body read deadline after the request is finished. Reading
php://inputafterfrankenphp_finish_request()dereferenced the nil'd-out HTTP/2 stream state and crashed the process; the deadline is now skipped once the context is done by @dunglas in #2538. Fixes #2535.
📖 Documentation
- Add a PSR-15 worker example by @dunglas in #2539.
- Remove title case in docs by @alexandre-daubois in #2534.
- Update translations by @github-actions in #2537.
Full Changelog: v1.12.5...v1.12.6
v1.12.5
FrankenPHP 1.12.5 is a security release. It fixes two disclosed vulnerabilities — an information leak in the default Docker welcome page and a cross-request session ID leak in worker mode — plus a batch of crash and hang fixes in worker mode and the CGI layer. Every user should upgrade, especially anyone running the official Docker images or the session extension as a shared module.
🔒 Security & Hardening
- Docker images no longer serve
phpinfo()by default. The default/app/public/index.phpranphpinfo(), so any derived image that didn't ship its own index leaked environment variables (often holding secrets),php.inidirectives, versions, and system paths. Both the Debian and Alpine images now ship the same static, script-free welcome page used by the RPM/deb packages by @dunglas in #2524. See GHSA-cj57-c655-p798. - Session ID no longer leaks across worker requests when the session extension is a shared module.
PS(id)wasn't reset between requests whenHAVE_PHP_SESSIONwas undefined at compile time, sosession_start()could reuse the previous request's session id and hand one client another client's session. Statically-linked builds were unaffected by @dunglas in #2523. See GHSA-v3ph-cgqh-r8p5. - Slow-POST protection by default. A client that stalls a request body indefinitely used to hold a PHP thread for the life of the connection, exhausting the thread pool under
max_threads.php_server/phpdeployments now enforce a 60s idle timeout on body reads out of the box (matching nginx'sclient_body_timeout), configurable via the newrequest_body_timeoutdirective or0to disable. Library users get the same control viaWithRequestBodyTimeoutby @iliaal in #2465.
🐛 Fixes
- Fix a heap-buffer-overflow read when parsing a short
header("HTTP/...")status line by assuming the code from PHP's ownsapi_update_response_code()instead of reparsing it by @iliaal in #2464. - Guard against a panic (and process crash) from a malformed
RemoteAddrwhen stripping IPv6 brackets in server variable registration by @iliaal in #2463, and a related panic on malformedRemoteAddrin the CGI variable builder by @alexandre-daubois in #2484. - Fix queued requests getting stuck on replaced channels by reusing created-once channels by @henderkes in #2470.
- Fix long-running CLI scripts hanging when a
pcntlsignal reached the Go runtime instead of the PHP handler by @henderkes in #2445. - Fix hanging reboots on threads that were upscaled and then downscaled by @AlliBalliBaba in #2510, following up on the thread-reboot-on-
opcache_reset/watcher-change fix by @AlliBalliBaba in #2364. - Deduplicate registration-time duplicates produced by
matchdirectives by @henderkes in #2487. php_server's environment variables are now available in the sandboxed environment by @henderkes in #2451.- extgen: correct a C parameter cast in generated class method wrapper calls by @alexandre-daubois in #2436.
⚡ Performance Improvements
- Fold a 3-instruction TLS load into a single
mrson aarch64 by @henderkes in #2512.
📖 Documentation
- Add guides for deploying on macOS and Windows by @m-this.
- Document
pcovandimagickincompatibilities in known issues by @alexandre-daubois in #2492. - Chinese translations for logging and observability docs by @pierresh in #2515.
- Italian translation of the docs by @garak in #2405.
💖 New Contributors
- @iliaal made their first contribution in #2464.
- @m-this made their first contribution in #2502.
- @garak made their first contribution in #2405.
Need help hardening a worker-mode deployment against session leaks and slow-POST DoS, or auditing your Docker images before they ship secrets to the public? Les-Tilleuls.coop — the team behind FrankenPHP — provides professional support, consulting, custom development, and training. Get in touch: contact@les-tilleuls.coop.
Full Changelog: v1.12.4...v1.12.5
v1.12.4
FrankenPHP 1.12.4 is a hardening and stability release. It pulls in upstream security fixes from Caddy 2.11.4 and Mercure 0.24.2, closes a class of HTTP header spoofing, and fixes several crashes and data races in worker mode. Every user should upgrade.
The headline is defense-in-depth against underscore-header spoofing. CGI maps dashes to underscores (Foo-Bar becomes HTTP_FOO_BAR), so a client-supplied Foo_Bar header is indistinguishable from a legitimate Foo-Bar in $_SERVER and can spoof any header an app or upstream proxy trusts (forwarded-for, auth, etc.). The bundled Caddy 2.11.4 now ignores header fields containing underscores at the server layer, and FrankenPHP documents the risk for code using the Go API directly.
🔒 Security & Hardening
- Underscore header spoofing blocked at the server layer. The bundled Caddy 2.11.4 now ignores HTTP header fields whose name contains an underscore, preventing collisions with the dash-to-underscore CGI mapping (reported by @Vincent550102, patched by @dunglas upstream).
NewRequestWithContextnow documents the risk for direct Go API users by @dunglas in #2460. - Caddy 2.11.4 security patches bundled: TLS client-auth fix, Windows backslash normalization in the path matcher, rewrite placeholder re-expansion fix, and a patch for GHSA-vcc4-2c75-vc9v. See the Caddy 2.11.4 release notes.
- Mercure 0.24.2 security hardening bundled for the Mercure Caddy module: SSE field injection via
id/type(CWE-93) now rejected, reserved/.well-known/mercuretopic forgery blocked,Last-Event-IDmetadata disclosure fixed, and DoS amplification caps added. See the Mercure 0.24.2 release notes. - Security model documentation describing FrankenPHP's trust boundaries and what qualifies as a security issue by @alexandre-daubois in #2455.
🐛 Fixes
- Fix
ext-parallelcrashes by correctly propagating the parent thread index viaSG(server_context)by @henderkes in #2438. - Clear
in_save_handlerstate that blocked the subsequent close handler by @henderkes in #2443. - Fix a data race in metrics by replacing the mutex with a read-write mutex by @alexandre-daubois in #2450 and removing redundant shutdown assignments by @henderkes in #2452.
- Report
headers_sent()asfalseunder CLI emulation by @henderkes in #2453.
⚡ Internal Improvements
- Drop the unreachable space-to-underscore replacement in header names (Go's net/http already rejects spaces) by @dunglas in #2441.
- Make UPX packing opt-in via the
COMPRESSenv var by @dunglas in #2429. - Dependency updates including Caddy 2.11.4 and Mercure 0.24.2 in #2454 and #2462.
📖 Documentation
- Add a WoltLab Suite example by @SoftCreatR in #2428.
- Update the incompatibilities section by @henderkes in #2420.
💖 New Contributors
- @SoftCreatR made their first contribution in #2428.
Need help adopting FrankenPHP, hardening a PHP application against header-spoofing and real-time security issues like these, or auditing your worker setup for races? Les-Tilleuls.coop — the team behind FrankenPHP — provides professional support, consulting, custom development, and training. Get in touch: contact@les-tilleuls.coop.
Full Changelog: v1.12.3...v1.12.4
v1.12.3
This release fixes CVE-2026-45062 (high, CVSS 8.1): unsafe Unicode handling in CGI path splitting let an attacker have a non-.php file executed as PHP via a crafted URL, in any deployment where attacker-controlled file names land on the served filesystem. All users on v1.11.2 through v1.12.2 should upgrade.
It also brings a ~7-8% Hello World throughput bump from a refreshed PGO profile, configurable per-thread request limits, persistent-zval helpers for sharing state across threads, a cross-platform force-kill primitive for stuck PHP threads, correct SCRIPT_NAME / PHP_SELF / PATH_INFO server variables, and a long series of frankenphp extension-init (extgen) generator fixes by @alexandre-daubois.
Released binaries now carry SLSA build-provenance attestations — verify with gh attestation verify <binary> --owner php or gh attestation verify oci://docker.io/dunglas/frankenphp@sha256:... --owner php.
🔒 Security
- Unsafe Unicode handling in CGI path splitting allowed execution of non-PHP files (GHSA-3g8v-8r37-cgjm / CVE-2026-45062). Reported by @KC1zs4.
🚀 Features
- Configurable
max_requestsfor PHP threads by @nicolas-grekas in #2292 - Persistent-zval helpers (deep-copy zval trees across threads) by @nicolas-grekas in #2366
- Cross-platform force-kill primitive for stuck PHP threads by @nicolas-grekas in #2365
- Release binaries now ship with SLSA build-provenance attestations by @dunglas in #2418
🐛 Fixes
- Set
$_SERVERvariablesSCRIPT_NAME,PHP_SELF, andPATH_INFOcorrectly by @henderkes in #2317 - Fix dead forked
pthread_forkchildren by @henderkes in #2332 - Fix upstream BC break on
INI_INT()macro by @zeriyoshi in #2387 - Caddy: reject invalid
split_pathat provision time by @alexandre-daubois in #2350 extgenparser hardening by @alexandre-daubois: better error handling (#2370), emit warnings to stderr (#2374), resetiotaper const block (#2375), escape control chars in C string literals (#2377), extract Go function bodies viago/ast(#2379), symmetric Go type compatibility check (#2380)
⚡ Performance and Internal Improvements
- Use PGO to improve FrankenPHP's Go performance (7-8% Hello World throughput) by @henderkes in #2361
perf(extgen): hoist const block regexes out of parser loop by @alexandre-daubois in #2378refactor: adddrain()seam tothreadHandlerinterface by @nicolas-grekas in #2367refactor(extgen): share signature and parameter parsing helpers by @alexandre-daubois in #2376
📝 Documentation
- Improve worker docs, add internals docs by @dunglas in #2334
- Add SEO frontmatter,
llms.txt, and code-block hygiene by @dunglas in #2394 - Fix migration guide menu entry by @alexandre-daubois in #2373
- Adjust volume mount path in
migrate.mdby @francislavoie in #2337 - Fix Laravel trusted proxies URL by @mtmn in #2359
- Update wording in extensions documentation by @SpencerMalone in #2338
💖 New Contributors
- @zeriyoshi made their first contribution in #2387
- @mtmn made their first contribution in #2359
Need help adopting FrankenPHP, hardening a PHP application against issues like CVE-2026-45062, or squeezing more performance out of your workers? Les-Tilleuls.coop — the team behind FrankenPHP — provides professional support, consulting, custom development, and training. Get in touch: contact@les-tilleuls.coop.
Full Changelog: v1.12.2...v1.12.3
v1.12.2
This release includes several new features, bug fixes, and performance improvements. It also addresses a critical cache key collision vulnerability in Mercure (GHSA-hwr4-mq23-wcv5).
🚀 Features
- Add more metrics in
ThreadDebugStateby @alexandre-daubois in #2282
🐛 Fixes
- Fix fatal PHP shutdowns by @AlliBalliBaba in #2293
- Fix race condition in auto-scaler during Caddy config reload by @nicolas-grekas in #2318
- Fix
opcache_preloadin PHP 8.2 by @AlliBalliBaba in #2284 - Force reload in FrankenPHP service configuration by @kitro in #2281
- Skip
README.mdgeneration inextension-initcommand if it exists by @IndraGunawan in #2283 - Remove
cdbefore call tospc dump-extensionsby @fastnloud in #2328
⚡ Performance and Internal Improvements
- Extend table on environment startup instead of letting
zend_hash_copydo it by @henderkes in #2272 - Hoist
LoaderFuncto package-level variable inphpheadersby @dunglas in #2053
📝 Documentation
- Add Symfony-specific page by @dunglas
- Add migration guide by @alexandre-daubois
- Add observability page by @alexandre-daubois
- Add trusted proxies section by @alexandre-daubois
- Add autocompletion documentation by @alexandre-daubois
- Improve Dockerfile for hardened images by @dunglas
- Update extension generator documentation for a more natural order by @alexandre-daubois
- Add IDE (GoLand/CLion) setup to
CONTRIBUTING.mdby @henderkes - Add French translation for hot reloading by @Ehyiah
💖 New Contributors
- @Ehyiah made their first contribution in #2105
- @nicolas-grekas made their first contribution in #2294
- @kitro made their first contribution in #2281
Full Changelog: v1.12.1...v1.12.2
v1.12.1
What's Changed
🐛 Bug Fixes
- Fix PHP startup errors when ini files contain environment variables by @henderkes in #2252
- Fix sigsev on bind permissions denied by @henderkes in #2251
📖 Documentation
- Update README for Windows, other minor changes by @dunglas in #2249
- Revise bug report template for improved instructions by @dunglas in #2181
- Improve hot reload, add missing features by @dunglas in #2261
- Sync all translations with the English ones
New Contributors
- @github-actions[bot] made their first contribution in #2206
Full Changelog: v1.12.0...v1.12.1
v1.12.0
What's Changed
Official, native Windows support has arrived!
This highly anticipated release brings 100% compatibility, Worker Mode, and Hot Reloading to Windows, delivering up to a 3.6x performance boost over traditional Nginx/PHP-FPM setups. Thanks to new compiler capabilities in Go 1.26, FrankenPHP now links directly against official Visual Studio-compiled PHP binaries for ultimate stability and full extension support.
Huge thanks to Intelligence X and Les-Tilleuls.coop for sponsoring this milestone.
Learn more about the story of the Windows port in this dedicated blog post.
This version also includes some performance optimizations and Caddy 2.11.2.
✨ New Features
- Windows support by @dunglas, @henderkes and many other contributors in #2119, #2227 and #2228
- Add configurable
max_idle_timefor autoscaled threads by @firecow in #2225
🚀 Performance Improvements
- Move sandboxed environment to the C side by @AlliBalliBaba in #2058
- Refactor CGI strings creation by @AlliBalliBaba in #2188
- Use ldflags to set Server header by @dunglas in #2221
📖 Documentation
- Spanish translation by @PhilDaiguille in #2096
- Improved hardened Docker image by @AlliBalliBaba in #2229
- Contributing on Windows by @dunglas in #2222
New Contributors
- @PhilDaiguille made their first contribution in #2096
- @firecow made their first contribution in #2225
Full Changelog: v1.11.3...v1.12.0
v1.11.3
This release restores application stability by reverting the unreliable worker mode INI reset introduced in version 1.11.2, upgrades Caddy to 2.11, and bumps the PHP version included in static binaries to PHP 8.5 to deliver new language features and performance gains, though the MS SQL Server and memcache extensions have been temporarily removed due to 8.5 incompatibility.
What's Changed
🐛 Bug Fixes
- Worker: Revert ini reset, keep session fixes (#2139) by @dunglas in #2217
- Worker: Always ignore user abort by @AlliBalliBaba in #2189
- Metrics: Only report workers ready when actually ready by @withinboredom in #2210
- Embed: Fix relative embed paths support by @henderkes in #2199
- Fix
nomercuretag usage by @tehmaestro in #2212
✨ New Features
- Upgrade to Caddy v2.11 by @henderkes in #2214
- Update static binaries PHP version to 8.5 by @henderkes in #2168
- Packages: Add restart policies to FrankenPHP systemd service by @henderkes in #2191
- Embed: Allow to customize the extraction path by @dunglas in #2198
Documentation
New Contributors
- @tehmaestro made their first contribution in #2212
Full Changelog: v1.11.2...v1.11.3
v1.11.2
Important
Security Update: This release addresses three security vulnerabilities, including a critical path confusion issue allowing arbitrary file execution and a session leak in worker mode. Immediate upgrade is strongly recommended.
Beyond security, this release delivers significant performance improvements by upgrading the compiler to Go 1.26. Users can expect a 10-40% faster Garbage Collector and ~30% faster CGO calls, resulting in significantly reduced latency for PHP applications.
We have also improved stability by addressing race conditions during shutdown, resolving segmentation faults in edge cases (such as early shutdown or specific extension registrations), and refining the handling of $_SERVER and HTTP Basic Auth.
What's Changed
🛡️ Security Fixes
- GHSA-g966-83w7-6w38: Path confusion via Unicode casing in CGI path splitting could allow execution of arbitrary files. Fixed by @AbdrrahimDahmani and @dunglas in commit 04fdc0c.
- GHSA-r3xh-3r3w-47gp: Fixed a session leak between requests handled by workers. Fixed by @xavierleune in commit 24d6c99.
- GHSA-x9p2-77v6-6vhf: Fixed delayed propagation of security fixes in upstream base Docker images. Fixed by @opctim in commit be2d6b9.
- Prevent potential cache pollution issues in CI builds by @dunglas in #2164
🐛 Bug Fixes
- Ensure
$_SERVER['PHP_SELF']always starts with a slash by @dunglas in #2172 - Let PHP handle HTTP Basic Authorization headers natively by @AlliBalliBaba in #2142
- Handle symlinking edge cases correctly by @withinboredom in #1660
- Prevent segmentation faults on early shutdown by @AlliBalliBaba in #2120
- Fix race condition in thread shutdown during drain by @dunglas in #2182
- Worker: Initialize
$_REQUESTcorrectly in worker mode by @xavierleune in #2136 - Worker: Reset INI settings and
$_SESSIONif changed during a worker request by @xavierleune in #2139 - Ext: Fix segmentation fault when registering multiple extensions by @y-l-g in #2112
- Extgen: Make the generator idempotent and avoid touching the original source by @alexandre-daubois in #2011
- Extgen: Correctly handle const blocks to declare iota constants by @alexandre-daubois in #2086
- Extgen: Use fast ZPP (Zend Parameter Parsing) by @alexandre-daubois in #2088
- Static: Don't overwrite
SPC_CMD_VAR_FRANKENPHP_XCADDY_MODULESunconditionally by @henderkes in #2135 - Embed: Fix relative paths not being resolved correctly by Static PHP CLI when embedding an app by @henderkes in #2093
- Embed: Correct path to Composer's
installed.jsonby @Jellyfrog in #2127
🚀 Performance Improvements
- Compile with Go 1.26 (includes 10-40% faster garbage collector and 30% faster CGO calls) by @alexandre-daubois and @dunglas in #2178
- Various internal optimizations by @dunglas in #2175
✨ New Features
- Packages: Add apk repository for Alpine Linux by @henderkes in #2099
Documentation
Note
Translations are now automated using an LLM.
New Contributors
- @Jellyfrog made their first contribution in #2127
- @xavierleune made their first contribution in #2138
- @damienfern made their first contribution in #1900
Full Changelog: v1.11.1...v1.11.2
v1.11.1
What's Changed
- fix: crash when using the logger outside of the a request context by @lobre in #2089
- fix:
frankenphp_log()level parameter must be optional by @dunglas in #2085 - fix(caddy): use default patterns when hot_reload is alone by @dunglas in #2081
New Contributors
Full Changelog: v1.11.0...v1.11.1
