Table of Contents

PHP RFC: Limit maximum number of filter chains

Introduction

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.

Proposal

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.

Examples

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)

Backward Incompatible Changes

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.

Proposed PHP Version(s)

RFC Impact

To the Ecosystem

Most developers will notice no change. Security scanners and WAFs may be simplified as they can rely on the engine's built-in protection.

To Existing Extensions

Minimal to none, as this logic resides within the core PHP stream wrapper for php://.

To SAPIs

No specific impact to CLI, FPM, or others.

Open Issues

Future Scope

Voting Choices

Implement limiting the number of Filter Chains in php://filter?

Primary Vote requiring a 2/3 majority to accept the RFC:

Implement $feature as outlined in the RFC?
Real name Yes No Abstain
Final result: 0 0 0
This poll has been closed.

Patches and Tests

There's already an existing merge request, and I am willing to do some work on this.

https://github.com/php/php-src/pull/16699

Implementation

After the RFC is implemented, this section should contain:

  1. the version(s) it was merged into
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature

References

Rejected Features

Keep this updated with features that were discussed on the mail lists.

Changelog