← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

PHP Stream Wrappers

php PHP 5.0+ Advanced
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list semgrep and phpstan as the tools, and the code_pattern describes phar:// or data:// in user-controlled paths — these require a SAST rule (semgrep) or static analyser (phpstan) to catch reliably. A default linter would not flag scheme usage in file function arguments, and the misuse is silent at runtime until an attacker triggers it.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is essentially a targeted call to stream_wrapper_unregister() for dangerous wrappers and whitelisting allowed schemes — a small, localised change. The common_mistakes suggest fixing input validation at the point of file function calls, which is a pattern-level fix rather than a one-liner, but doesn't require touching multiple files architecturally.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to scope is web and cli contexts broadly, but the actual burden is confined to the layers where user-supplied paths enter file functions. Most of the codebase is unaffected; the tax is paid at validation/input-handling boundaries rather than being load-bearing across the whole system.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field reveals that developers believe stream wrappers are only used internally by PHP, not realising that custom wrappers can intercept any file operation and that user-controlled paths with phar:// or data:// enable full attack chains. This contradicts the intuitive mental model that file functions simply open files — the 'obvious' assumption that file paths are safe strings is wrong, which is a serious behavioural contradiction from what developers expect.

About DEBT scoring →

Also Known As

PHP stream wrappers php:// file:// stream custom stream

TL;DR

PHP's I/O abstraction layer — built-in wrappers like file://, php://, phar://, and http:// let file functions operate over any protocol.

Explanation

Stream wrappers allow PHP's file functions (fopen, file_get_contents, include) to work over arbitrary protocols. Built-ins include: file:// (local filesystem), http:// / https:// (remote, requires allow_url_fopen=On), php:// (php://input, php://memory, php://temp), phar:// (PHAR archives), and data:// (inline data). Custom wrappers are registered via stream_wrapper_register(). Security: many vulnerabilities exploit unexpected wrapper acceptance — SSRF via http://, PHAR injection via phar://, source disclosure via php://filter. Always validate and restrict the wrappers accepted in user-controlled path arguments.

Watch Out

php://filter/convert.base64-encode/resource=config.php can exfiltrate source files through any include() or file_get_contents() that accepts user-controlled paths.

Common Misconception

Stream wrappers are only used by internal PHP functions. Custom stream wrappers can intercept and virtualise any file operation — useful for in-memory filesystems in tests, encrypted file access, and remote storage abstraction behind standard file functions.

Why It Matters

PHP stream wrappers (php://, file://, http://, phar://) allow the same file functions to work across different data sources — misunderstanding them leads to SSRF and PHAR injection vulnerabilities.

Common Mistakes

  • Not restricting allowed stream wrappers when processing user-supplied paths — phar:// and data:// enable attack chains.
  • Using php://input for raw request body reading but not limiting the maximum read size.
  • Not knowing that php://memory and php://temp are useful for in-memory file operations in tests.
  • Allowing user-controlled file paths in file functions without stripping or whitelisting the scheme.

Code Examples

✗ Vulnerable
// User-controlled path with unrestricted wrappers:
$path = $_GET['file'];
$content = file_get_contents($path); // phar://, http://, file:// all work
// Attacker: ?file=phar://uploads/img.jpg — deserialization
// Attacker: ?file=php://filter/convert.base64-encode/resource=/etc/passwd
✓ Fixed
// Built-in wrappers:
file_get_contents('file:///var/www/data.txt');   // local file
file_get_contents('php://input');                 // raw POST body
\$h = fopen('php://temp', 'r+');                  // temp (mem → disk)
fwrite(\$h, 'data'); rewind(\$h);
echo stream_get_contents(\$h);

// php://filter — transform on read:
\$b64 = file_get_contents('php://filter/convert.base64-encode/resource=file.txt');

// Custom stream wrapper:
class LogStream {
    public function stream_open(\$path, \$mode, \$options, &\$opened): bool { return true; }
    public function stream_write(string \$data): int {
        error_log(\$data); return strlen(\$data);
    }
    public function stream_eof(): bool { return true; }
    public function stream_read(int \$count): string { return ''; }
}
stream_wrapper_register('log', LogStream::class);
file_put_contents('log://channel', 'message sent');

Added 15 Mar 2026
Edited 22 Mar 2026
Views 19
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 2 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 2 ChatGPT 2 Ahrefs 1 Google 1
crawler 12 crawler_json 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Register custom stream wrappers with stream_wrapper_register() to abstract file system access — but unregister dangerous ones (phar://) in production if your app doesn't use them
📦 Applies To
PHP 5.0+ web cli
🔗 Prerequisites
🔍 Detection Hints
phar:// or data:// or php:// in user-controlled file paths; custom stream wrapper without input validation; stream wrappers not restricted on production
Auto-detectable: ✓ Yes semgrep phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-98 CWE-22

✓ schema.org compliant