Skip to content

v1.13.5

Latest

Choose a tag to compare

@dunglas-release dunglas-release released this 05 Nov 12:01
· 1 commit to main since this release
a3663e9

FrankenPHP 1.13.5 is a security release. It fixes 17 vulnerabilities in FrankenPHP. The most severe let php_server run an uploaded non-PHP file as PHP. Several others affect the default php_server configuration: an open redirect, an HTTP/2 Host spoofing issue, a crash a client can trigger with the official Docker images' PHP settings, and slow request bodies that block every PHP thread. This release also upgrades to Caddy 2.11.9, which brings security fixes in Caddy itself, and to Mercure 1.1.6. Upgrading is strongly recommended.

🔒 Security

  • High, php_server: A file whose name doesn't end in a split extension could be run as PHP, for instance /uploads/photos.php.php/avatar.jpg. An attacker able to upload a file under the document root could execute it (GHSA-j99q-3wr8-xj43).
  • Medium, php_server: The trailing-slash redirect for directories echoed the raw request path, so //attacker.example/..%2fblog redirected to another host. The redirect is now relative, like Caddy's php_fastcgi (GHSA-jvmv-5538-pqpg).
  • Medium, HTTP/2: A host header field sent next to :authority set $_SERVER['HTTP_HOST'] to a host other than the one Caddy routed and access-checked the request on (GHSA-2725-rh2w-9j9w).
  • Medium, request_body_timeout: The timeout didn't stop slow request bodies, so an unauthenticated client could block every PHP thread with one slow connection per thread. Fixed by Caddy 2.11.8 and later (GHSA-j45x-h238-h4xx).
  • Medium, crash: A PHP request startup failing repeatedly on a regular thread, for instance with more parameters than max_input_vars and PHP's default settings, crashed the process with a segmentation fault (GHSA-5359-vg53-5464).
  • Medium, crash: exit() or die() with a negative status, such as die(-1), made FrankenPHP panic and stop (GHSA-q6vv-3p75-53wr).
  • Medium, Caddy rules bypass: Dot segments and encoded slashes after a PHP script, such as /admin/tool.php/../../missing.php, let requests run a script that a Caddy path rule was meant to deny (GHSA-2x4j-r638-wxff). On Windows, the same check now also covers backslashes by @dunglas in #2810.
  • Medium, env: A client's Authorization: Basic header replaced the REMOTE_USER value set with env, and four other variables also overrode env values. Only 1.12.0 and later are affected (GHSA-388m-835f-7723).
  • Medium, named routes: A php_server or php directive in a Caddy named route could run with the root, env values and workers of another site. Only 1.13.0 and later are affected (GHSA-g7pw-whv8-97j7).
  • Medium, source disclosure: A php_server with a worker match rule could serve the source of scripts using an extra split extension, or of any script behind some rewrites (GHSA-v7hf-4gqv-hf8p).
  • Medium, worker mode: Destructors of objects from a previous request, including session objects, ran while the next client's output was active, sending output and cookies to the wrong client (GHSA-8qcf-v46r-g2mc).
  • Medium, embedded apps: The extracted app directory was deleted on configuration reloads while the server kept serving from it, so another local user could recreate it with their own code. Incomplete fix of GHSA-6q3j-62j9-f9hh, only 1.13.2 and later are affected (GHSA-j2f3-wxf2-8qgv).
  • Low, Caddyfile disclosure: With the minimal documented layout, php_server served the Caddyfile stored in the document root (GHSA-xh92-4p94-ch7x).
  • Low, autoscaling: FrankenPHP panicked when the operating system refused to create a new PHP thread (GHSA-hfxc-999w-mp67).
  • Low, PATH_INFO: Functions such as getlastmod() and session cache limiters let clients probe the existence and modification time of files under the document root (GHSA-g9v4-rp77-rv76).
  • Low, extension workers: Workers.SendRequest() ran arbitrary files below the working directory when its worker wasn't running (GHSA-cp2q-fc46-38f5), and Workers.SendMessage() freed a zval owned by the caller (GHSA-28vm-87fh-3px5). Only custom builds linking a Go extension that uses these experimental APIs are affected.

Most of these vulnerabilities were found by Anthropic's OSS Scanner.

⚠️ Breaking Change

  • Worker mode: Between requests, FrankenPHP now only resets state built from the HTTP request: superglobals (except $_ENV), the request body, response headers and output, the session and the URL rewriter. strtok(), http_get_last_response_headers(), error_get_last() and the libxml errors persist again, like userland state does. Call error_clear_last(), libxml_clear_errors() or http_clear_last_response_headers() if you need a clean state by @dunglas in #2790.

✨ New Features

  • Populate $_SERVER['SERVER_ADDR'] with the IP address that accepted the connection, like Caddy's FastCGI transport, nginx and Apache by @dunglas in #2809.

🐛 Bug Fixes

  • Return 413 when the request body exceeds Caddy's request_body max_size instead of passing a truncated body to PHP by @dunglas in #2785.
  • Return 404 No input file specified. when the script can't be opened, like php-fpm, instead of a 200 with a fatal error by @dunglas in #2791.
  • Destroy persistent resources, such as PDO::ATTR_PERSISTENT connections, when a PHP thread exits. With PHP 8.4 and later, each worker restart leaked them, until the database refused new connections by @andreasisaak in #2812.
  • Extensions: Custom Go extensions stay registered after PHP restarts (file watcher, RestartWorkers(), config reloads) by @aguinaldotupy in #2788.
  • Extension workers: SendRequest() reaches workers declared without a name, and SendMessage() returns ErrNotRunning after shutdown instead of waiting forever by @nicolas-grekas in #2786.
  • Worker mode: Warnings raised while parsing the request no longer reach the previous request's error handler and can be read with error_get_last(), as with FPM by @AlliBalliBaba in #2792.
  • Fix a memory leak reported by OSS-Fuzz in the cached HTTP method strings by @dunglas in #2789.
  • Upgrade to Caddy 2.11.9, Mercure 1.1.6 and Vulcain 1.4.6. php_server keeps returning Caddy's 404 for unknown paths in sites without an index.php by @dunglas in #2814.

⚡ Performance Improvements

📖 Documentation

  • Select a single platform in the local static build commands by @opctim in #2805.
  • Update translations in #2808.

🙏 Sponsor the Maintainers

The "vulnapocalypse" caused by AI adds a lot of work for us: AI-powered scanners now report vulnerabilities faster than ever, and every report has to be reproduced, fixed and disclosed by a maintainer. This release alone fixes 17 advisories. Thank you to our sponsors, who make this work possible!

If you or your company rely on FrankenPHP, please consider sponsoring its maintainers:

💖 New Contributors

Full Changelog: v1.13.4...v1.13.5