This RFC proposes to introduce a limit on the number of filters that can be chained within a php://filter URL. The primary goal is to mitigate a class of security vulnerabilities where Local File Inclusion (LFI) is elevated to Remote Code Execution (RCE) via complex, generated filter chains.
Currently, an attacker can use a long sequence of convert.iconv.* and convert.base64 filters to craft arbitrary content (like a PHP shell) out of any file on the disk, or even from an empty resource. By limiting the chain length to a reasonable number (e.g., 5 or 10), we can effectively disable these automated exploitation tools while maintaining support for legitimate use cases.
The proposal seeks to limit the number of individual filter components allowed in a single `php://filter` string, configured with an INI setting such as `filter.max_chain_depth`. This limit applies specifically to the parsing of php://filter URLs (e.g., via fopen, include, file_get_contents). When the limit is exceeded, PHP should emit a Warning and the stream open operation should return false.
Still works:
var_dump(file_get_contents("php://filter/string.toupper|string.rot13/resource=data://text/plain,hello")); // string(5) "URYYB"
Fails:
var_dump(file_get_contents("php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|...[48 more].../resource=php://temp")); // Warning: file_get_contents(...): filter chain depth of 50 exceeds the limit of 32 // bool(false)
This is a backward incompatible change for any application that legitimately chains more filters than the defined limit.
A survey of open-source code (Sourcegraph) indicates that the vast majority of php://filter usages involve 1 filter, and occasionally 2. Legitimate use cases for 5 or more filters were not found outside of CTF challenges and exploit payloads.
A malicious payload typically takes more than 100 filters, so there is a large margin where malicious use is blocked but legitimate use is not.
Most developers will notice no change. Security scanners and WAFs may be simplified as they can rely on the engine's built-in protection.
Minimal to none, as this logic resides within the core PHP stream wrapper for php://.
No specific impact to CLI, FPM, or others.
Implement limiting the number of Filter Chains in php://filter?
Primary Vote requiring a 2/3 majority to accept the RFC:
There's already an existing merge request, and I am willing to do some work on this.
After the RFC is implemented, this section should contain:
Keep this updated with features that were discussed on the mail lists.