Symfony and PHP2Shell
Symfony runs on PHP, and PHP2Shell is two serious flaws in PHP itself. Updating Symfony does not fix them. Update PHP on the server, then restart PHP.
Last reviewed . Rules of .
What to do
- Find the PHP version that serves your site (see below).
- Update PHP to a fixed release that your Symfony version supports: 8.2.35, 8.3.36, 8.4.27 or 8.5.12. Later releases in the same branch also work.
- Restart PHP-FPM or your web server and your Messenger workers.
- If your host runs PHP for you, ask them to do this and to confirm the version.
Check this too: a profiler running in production. If your site sends an X-Debug-Token header, the Symfony profiler is running on it. This is a separate problem from PHP2Shell.
Symfony says never to enable the profiler in production, because it leads to major security vulnerabilities. Turn it off now, whatever your PHP version. See Check for an exposed profiler.
What the checker can see
The checker reads one ordinary page of your site. For a Symfony site it looks for:
- An
X-Debug-TokenorX-Debug-Token-Linkheader. These headers mean that the Symfony profiler is on. The checker then shows a "Profiler exposed" warning. It notes only that the header is there, and never reads or shows its value. - The PHP version in the
X-Powered-Byheader, if your server sends it. PHP sendsX-Powered-Byunlessexpose_phpis turned off, and it is on by default. - A
PHPSESSIDcookie, or links and forms that point to.phppages.
With the profiler off, a Symfony site sends no Symfony signal, so the checker cannot tell that it runs Symfony, or which version. The PHP2Shell result depends on the PHP version alone.
Where to see the PHP version
- On the command line:
php -vshows the version of the command-line PHP. Your web pages can be served by a different version or build, so check that one as well. - In your hosting panel: look for the PHP version of each site. If you are not sure which one serves your site, ask your host.
- From outside:
curl -sI https://example.com/shows the response headers. Look forX-Powered-By. A missing header proves nothing either way.
Supported PHP versions
| Symfony | Status | Needs PHP | Support ends |
|---|---|---|---|
| 8.1 | Latest stable | 8.4.0 or later | January 2027 |
| 7.4 | Long-term support | 8.2.0 or later | Security fixes until November 2029 |
| 6.4 | Long-term support | 8.1.0 or later | Security fixes until November 2027 |
Pick a fixed PHP release at or above that minimum, and one that your app and its Composer packages support:
- Symfony 8.1: 8.4.27 or 8.5.12.
- Symfony 7.4: 8.2.35, 8.3.36, 8.4.27 or 8.5.12.
- Symfony 6.4: it allows PHP 8.1, but PHP 8.1 gets no new release from the PHP project. Move to 8.2.35 or later, or use a vendor build of 8.1 that has the fix.
Symfony 8.0 is no longer maintained: its support ended in July 2026.
How to update PHP
- Managed hosting: select a fixed PHP version in the hosting panel, or ask your host to install one.
- Your own server: update PHP with your system’s package manager. Some Linux distributions ship fixed builds that keep the old version number, so check the package rather than the number alone. See Fixed versions.
- Containers: rebuild the image on a fixed PHP base image and replace the running containers (our advice).
- Restart: the PHP2Shell researchers say to restart Apache, PHP-FPM and every long-running PHP worker after the update. A process that has not restarted still has the old PHP in memory.
- Messenger workers: run the
messenger:stop-workerscommand. Each worker finishes its current message and exits, and your process manager starts it again. - Run the checker again, and confirm the version with your host.
Check for an exposed profiler
When the Symfony profiler stores data about a request, it adds an X-Debug-Token header to the response. For responses that are not HTML, the X-Debug-Token-Link header holds the profiler URL. The stored profiles are listed under /_profiler.
To check, look at the response headers of your site:
curl -sI https://example.com/ | grep -i '^x-debug-token'
If you see either header, or if /_profiler opens in a browser:
- Turn the profiler off in production. Symfony installs it as a development-only package (
composer require --dev symfony/profiler-pack), so production should not load it. - Our advice: treat anything the profiler showed as known to others. Rotate the passwords and keys that the app uses.
Notes
- The flaws are in PHP, not in Symfony, so updating Symfony or its packages does not fix them. php.net says every PHP install that serves web requests is at risk.
- No configuration change is a complete workaround. Update PHP. If you have to wait, Mitigations lists interim measures.
- Security fixes for PHP 8.2 end on 31 December 2026. Plan a move to 8.3 or later.
- PHP 8.1 and older get no new release from the PHP project; only some vendors ship fixed builds for them.
- php2shell.com says the flaws can leak server memory, and that memory can hold passwords, tokens and keys. Our advice: if the server ran an affected PHP while reachable from the internet, rotate those secrets after the update.
Sources
- PHP security advisory, 21 October 2026 (php.net)
- GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
- GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
- Supported PHP versions (php.net)
- PHP2Shell research: upgrade steps (php2shell.com)
- expose_php setting (php.net manual)
- PHP command line options (php.net manual)
- Symfony releases (symfony.com)
- Symfony profiler (symfony.com)
- Symfony Messenger: deploying to production (symfony.com)
Check your site
The checker reads one ordinary page of your Symfony site, sends no attack traffic, and shows the public PHP signals it found.