In short: php-cgi is the oldest way of running PHP behind a web server and still runs on many servers, often unnoticed. The php-cgi vulnerability from PHP2Shell explicitly affects this operating mode. Patch, end all running php-cgi processes and plan the move to PHP-FPM.
What php-cgi is and where it still runs
PHP comes in several variants: as a command-line program, as an Apache module, as PHP-FPM and as php-cgi. php-cgi is a program that the web server starts and to which it hands requests via CGI or FastCGI. Without its own process management, it is simpler than PHP-FPM, but also less controllable.
Typical places to find it are older hosting panels, Apache with mod_fcgid, custom wrapper scripts for several PHP versions, and PHP on Windows with IIS via FastCGI. Agencies and public authorities also have servers that were set up years ago and have merely been kept running since.
The php-cgi vulnerability in PHP2Shell
PHP2Shell covers the vulnerabilities CVE-2026-109618 and CVE-2026-109619 in PHP itself, each with CVSS v4.0 9.2. Both allow malicious code to be executed without logging in. The PHP project explicitly names php-cgi among the affected operating modes, alongside PHP-FPM, mod_php, FrankenPHP and LiteSpeed.
The fixed versions are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. For PHP 8.1 and older there are no more official updates, only minimal source backports for 7.4, 8.0 and 8.1. php-cgi setups in particular run on old versions more often than average. php-cgi is also not affected for the first time: back in 2024, a vulnerability in php-cgi on Windows (CVE-2024-4577) caused a stir. Legacy setups of this kind therefore deserve particular attention.
Finding php-cgi on the server
The following commands only read and help you track down php-cgi. Paths and module names are examples.
# Running php-cgi processes with start time and user
ps -eo pid,lstart,user,cmd | grep -E 'php-cgi|php[0-9.]*-cgi' | grep -v grep
# Installed php-cgi programs
ls /usr/bin/php*-cgi /usr/lib/cgi-bin/php* 2>/dev/null
# Apache: is mod_fcgid or mod_cgi loaded?
apache2ctl -M 2>/dev/null | grep -Ei 'fcgid|cgi'
grep -RniE 'FcgidWrapper|AddHandler.*php|Action.*php' /etc/apache2 /etc/httpd 2>/dev/null
If you find FcgidWrapper entries or handlers that point to a php-cgi program, this operating mode is running. For every program you find, check the version with -v. For distribution packages, the changelog with the CVE numbers proves the patch, because backports often do not change the version number.
Patch and end all processes
Apply the update through the package manager or the source php-cgi comes from. After that, all running php-cgi processes must disappear. With mod_fcgid, Apache keeps processes on hand for a while; a full restart of Apache ends them.
# Restart Apache completely (Debian/Ubuntu or RHEL family)
systemctl restart apache2 # or: systemctl restart httpd
# Check: are there still php-cgi processes older than the update?
ps -eo pid,lstart,cmd | grep -E 'php-cgi' | grep -v grep
If php-cgi runs through its own process manager or a panel service, restart that. On Windows with IIS, recycle the application pools, see PHP on Windows and IIS.
If php-cgi runs with PHP 8.1 or older on a publicly reachable server, there is no official patch. Set the interim measures immediately and, following the BSI recommendation, consider taking the server offline temporarily.
Interim measures for php-cgi
php.net recommends interim measures that do not offer complete protection. With php-cgi, the values belong in the php.ini that the respective program loads, or in the server configuration. According to php.net, .user.ini files and ini_set() are not sufficient for session.upload_progress.enabled.
; php.ini of the php-cgi installation
session.upload_progress.enabled = 0
post_max_size = 8M
upload_max_filesize = 6M
With an upload function, php.net gives post_max_size = 32M. On PHP 8.5, fatal_error_backtraces=0 is added. You set memory limits through cgroups for the web server service, not through RLIMIT_AS or RLIMIT_DATA. Then restart all processes.
The way to PHP-FPM
In the long run, php-cgi is not a good choice. PHP-FPM offers pools per website, separate users, limits per pool, status pages and controlled restarts. The switch is usually easy to plan: install PHP-FPM, create pools, switch the web server to FastCGI towards PHP-FPM, remove wrapper scripts. What a clean setup looks like is shown in Securing Nginx with PHP-FPM. If an old PHP version is also running, combine the switch with the upgrade.
Until the switch has happened, you should review the existing configuration critically. The web server should only hand files ending in .php to php-cgi, and no paths that point to files that do not exist. In upload directories, PHP execution must not be possible. For wrapper scripts that load a separate php.ini per website, check whether those files undo the interim values. If a php-cgi program sits directly in a publicly reachable directory such as cgi-bin, it should be removed from there. Such legacy items often stem from installation guides of past years and are simply forgotten in later rebuilds. Document every finding with its path and purpose so that the later rebuild overlooks nothing.
What remains important: a patch does not remove malware that was planted earlier. Keep the logs from 20 October 2026 onward.
How does PHP SOS help?
- We track down php-cgi installations, wrappers and handlers and assign them to the websites.
- We patch, end all old processes and document the state.
- For PHP 8.1 and older, we plan the migration to a supported PHP version with you.
- As part of server hardening, we replace php-cgi with PHP-FPM with separate pools.
Frequently asked questions
Am I using php-cgi without knowing it?
That is more common than you would think. Older panels, FastCGI setups with mod_fcgid and PHP on Windows with IIS often start PHP as php-cgi. A process list or the Server API in phpinfo shows it reliably.
Is FastCGI the same as php-cgi?
Not quite. FastCGI is a protocol. PHP-FPM and php-cgi can both speak FastCGI, but php-cgi is the older, simpler program without pools and process management. PHP2Shell explicitly affects php-cgi.
What does classic CGI mean for PHP?
With classic CGI, the web server starts a new PHP process for every request. That is slow and rare today. More common is php-cgi behind mod_fcgid or FastCGI, where processes handle several requests.
Do I have to restart anything after the update?
Yes. In FastCGI setups, php-cgi processes keep running for a while. Restart the web server or the process manager, and check that no php-cgi process is older than the update.