It passed unanimously with 30 votes in favor, none against and 2 abstaining, well above the two-thirds it needed. Voting closed on June 26, 2026, and the limit is implemented in PHP 8.6.
Limit maximum number of filter chains
Limits php://filter URLs to 16 chained filters by default, blocking attacks that use long chains to turn file reads into code execution.
Implement a limit on the maximum number of filters as outlined in the RFC?
This poll has closed.
Summary
A php://filter URL lets you run a stream through filters, like base64 or rot13, as you read it, and you can chain many filters together with |. Attackers have learned to chain dozens or even hundreds of them. With enough filters, they can turn any file, even an empty one, into PHP code they control. This RFC from Sjoerd Langkemper caps how many filters a single php://filter URL can use, with a default limit of 16.
Why it helps
Long filter chains show up in real attacks:
- Running code. If an app does
include $_GET['a'], a filter chain can make it execute arbitrary code, not just files already on the server. - Reading files. With
file($_GET['a']), errors triggered by the chain can leak a file's contents even when the app never displays them. - Faking file types. A chain can make
/etc/passwdlook enough like an image to pass a type check.
The RFC lists how many filters each technique needs. A basic error-based trick takes 5, leaking a whole file takes more than 50, and building a web shell takes more than 100. A search of open-source code found that normal apps use 1 filter, and occasionally 2.
How it looks
Short chains still work:
var_dump(file_get_contents("php://filter/string.toupper|string.rot13/resource=data://text/plain,hello")); // string(5) "URYYB"
In PHP 8.6, going over 16 filters triggers a deprecation warning. If you set the limit yourself, going over it fails:
$ctx = stream_context_create(['filter' => ['max_filter_count' => 1]]); var_dump(file_get_contents("php://filter/string.toupper|string.rot13/resource=data://text/plain,hello", false, $ctx)); // Warning: ... Failed to open stream: too many filters in ... // bool(false)
You can raise the limit globally with stream_context_set_default(), but there's no php.ini setting for it. You can also attach filters one at a time with stream_filter_append(), which has no limit.
What it means for existing code
Most apps won't notice. If you chain more than 16 filters in one URL, you'll see a deprecation warning in PHP 8.6, and the RFC plans to make it an error in PHP 8.7. To keep that code working, set filter.max_filter_count in a stream context or switch to stream_filter_append(). Older PHP versions ignore the option, so it's safe to add now.