CVE-2026-62996 Overview
CVE-2026-62996 is a path traversal vulnerability [CWE-22] in the Smarty template engine for PHP. Smarty separates HTML/CSS presentation from application logic and is widely used in PHP applications. Versions from 5.0.0 up to but not including 5.8.4 fail to adequately restrict which PHP stream wrappers and filter chains can be referenced from a template. An attacker able to author or influence a template's stream: resource reference can supply a php://filter-wrapped resource name to read arbitrary local files accessible to the PHP process. The issue is fixed in Smarty version 5.8.4.
Critical Impact
Attackers with the ability to control template resource references can disclose sensitive local file contents outside the intended template and configuration scope.
Affected Products
- Smarty PHP template engine version 5.0.0 through 5.8.3
- PHP applications embedding Smarty and permitting user influence over template resource names
- Deployments using the stream: resource type without a restrictive security_policy
Discovery Timeline
- 2026-08-07 - CVE-2026-62996 published to NVD
- 2026-08-07 - Smarty releases version 5.8.4 addressing the issue
- 2026-08-07 - Last updated in NVD database
Technical Details for CVE-2026-62996
Vulnerability Analysis
The vulnerability resides in Smarty's StreamPlugin resource handler, which processes templates referenced with a stream: prefix. When a template references a resource such as stream:php://filter/..., Smarty resolves the path and passes it directly to fopen(). The nested wrapper scheme (for example php) is never checked against the configured security policy. This allows chained PHP stream filters, including convert.base64-encode, to read arbitrary local files and return their contents to the calling template context. The result is unauthorized disclosure of file contents readable by the PHP process, such as configuration files, credentials, or source code.
Root Cause
In BasePlugin::load(), the built-in stream sysplugin is matched before stream_get_wrappers() and isTrustedStream() are evaluated. Because the outer wrapper is stream, the inner wrapper carried in the resolved filepath is never validated. Setting Security::$streams = null therefore does not block nested wrappers such as php://filter.
Attack Vector
Exploitation requires an attacker to author or influence a template's resource name. The attacker crafts a resource reference such as stream:php://filter/convert.base64-encode/resource=/etc/passwd. Smarty rewrites the reference into a filepath and opens it with fopen(), streaming the filtered file contents back into the template output.
// Patch excerpt from src/Resource/StreamPlugin.php
// Source: https://github.com/smarty-php/smarty/commit/3c9f77a2e06ce319ae0092496af32cc8f3adc52e
$filepath = str_replace(':', '://', $source->getFullResourceName());
// Validate the underlying stream wrapper against the security policy.
// When the built-in "stream" resource type is used (e.g.
// stream:php://filter/...), BasePlugin::load() matches the "stream"
// sysplugin before the stream_get_wrappers()/isTrustedStream() check,
// so the nested wrapper ("php" here) is never validated. Parse the
// wrapper scheme from the resolved path and check it explicitly so that
// e.g. Security::$streams = null blocks it before fopen() (CWE-22/-441).
$smarty = $source->getSmarty();
if (is_object($smarty->security_policy) && ($_pos = strpos($filepath, '://')) !== false) {
$smarty->security_policy->isTrustedStream(strtolower(substr($filepath, 0, $_pos)));
}
$t = '';
$fp = fopen($filepath, 'r+');
if ($fp) {
while (!feof($fp) && ($current_line = fgets($fp)) !== false) {
// ...
}
}
The patch parses the wrapper scheme from the resolved path and explicitly calls isTrustedStream() on it before fopen() executes.
Detection Methods for CVE-2026-62996
Indicators of Compromise
- Template resource strings containing stream:php://filter, stream:php://, or other nested wrapper schemes.
- Web server or application logs showing template parameters that include convert.base64-encode/resource= or similar filter chains.
- Unexpected file reads of sensitive files such as /etc/passwd, .env, or config.php originating from the PHP process during template rendering.
Detection Strategies
- Inventory PHP applications and identify Smarty deployments with versions between 5.0.0 and 5.8.3 using composer.lock or vendor/smarty/smarty/CHANGELOG.md.
- Perform static analysis to locate call sites where user-controllable input reaches Smarty template resource names, template inheritance, or {include} directives.
- Search request logs and WAF telemetry for URL-encoded or plain occurrences of php://filter in parameters associated with template selection.
Monitoring Recommendations
- Alert on PHP-FPM or Apache worker processes opening files outside the expected template directory tree.
- Log Smarty exceptions and warnings, especially those emitted from Resource/StreamPlugin.php and the security policy layer.
- Correlate template rendering events with subsequent outbound transfers of large or base64-encoded response bodies.
How to Mitigate CVE-2026-62996
Immediate Actions Required
- Upgrade Smarty to version 5.8.4 or later across all affected applications.
- Audit application code for locations where template resource names, template files, or {include} targets can be influenced by untrusted input.
- Configure a Smarty Security_Policy and set $streams = null to disallow stream wrappers where they are not required.
Patch Information
The fix is available in Smarty GitHub Release v5.8.4 and merged via Pull Request #1195. Full technical context is documented in GitHub Security Advisory GHSA-rjhh-76wf-8xmw and the remediation commit.
Workarounds
- Enforce a Smarty security policy that blocks the stream: resource type and any nested wrappers not required by the application.
- Filter or reject user-supplied strings containing ://, php:, or filter/ before passing them to any Smarty API that resolves template resources.
- Restrict the PHP process's filesystem access using open_basedir and least-privilege file permissions to limit the blast radius of arbitrary file reads.
# Upgrade Smarty via Composer
composer require smarty/smarty:^5.8.4
composer update smarty/smarty
# PHP configuration hardening (php.ini)
allow_url_fopen = Off
allow_url_include = Off
open_basedir = /var/www/app:/tmp
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

