Unexpected clearing of $_SERVER superglobal when accessing $_ENV in PHP-FPM
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 40.4k
- Forks
- 8.1k
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 96
Description
Description
Summary:
When using PHP-FPM, accessing the $_ENV superglobal with filter_var() or directly can cause the $_SERVER superglobal to lose its values, specifically REMOTE_ADDR, which unexpectedly becomes null. Notably, this occurs even if the code accessing $_ENV is placed after an exit, which should prevent it from executing. This behavior does not occur when using PHP with other SAPIs, such as Apache’s mod_php.
Steps to Reproduce:
- Create a PHP script with the following content:
<?php
$remoteAddr = filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP);
if ($remoteAddr === null) {
echo 'REMOTE_ADDR is not set';
} elseif ($remoteAddr === false) {
echo 'Invalid IP address';
} else {
echo "IP Address: $remoteAddr";
}
exit;
// Accessing $_ENV with filter_var, which should not execute due to the exit above
$appEnv = filter_var($_ENV['APP_ENV'], FILTER_SANITIZE_SPECIAL_CHARS);
-
Run this script using PHP-FPM with either Nginx or Apache as the reverse proxy.
-
Expected Behavior: The script should display the client’s IP address from
$_SERVER['REMOTE_ADDR']and then terminate execution after theexitstatement, meaning the code below exit should never be executed or have any effect. -
Actual Behavior: The script displays "REMOTE_ADDR is not set", indicating that
$_SERVER['REMOTE_ADDR']is unexpectedlynull, despite the exit command being in place. This suggests that simply having thefilter_var($_ENV['APP_ENV']...line in the script is enough to cause this behaviour, even though the line should never actually run due to theexit. -
Modify the script to use
filter_inputfor$_ENV:
$appEnv = filter_input(INPUT_ENV, 'APP_ENV', FILTER_SANITIZE_SPECIAL_CHARS);
- Observed Behaviour: When filter_input is used instead of directly accessing
$_ENV, the issue does not occur, and$_SERVER['REMOTE_ADDR']is correctly set, even though this line should not execute due to the preceding exit.
Question:
Is this behavior expected when using PHP-FPM, or is it a quirk that should be addressed? The fact that this occurs even with the exit command in place suggests there might be an underlying issue in how PHP-FPM manages superglobals. If it’s expected, could it be documented more clearly to avoid confusion for developers relying on superglobals like $_SERVER and $_ENV?
PHP Version
PHP 8.3.10, observed down to PHP 5.6.40
Operating System
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the behavior with PHP-FPM using the script and versions described, then compare it with another SAPI such as Apache mod_php. Trace how filter_var() or direct $_ENV access relates to $_SERVER and REMOTE_ADDR, and check the existing FPM and superglobal tests. Done means the behavior is explained and corrected or documented, with coverage for the exit case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, php
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100