Smarty Security stream restriction bypass through stream: resource
smarty/smarty version 5.8.0 can read local files through PHP stream wrappers even when Smarty Security is enabled and all streams are disabled with Security::$streams = null.
The bypass uses Smarty's built-in stream: resource type. A template such as:
```smarty
{include file="stream:php://filter/read=convert.base64-encode/resource=/tmp/secret.tpl"}
```
is handled as Smarty resource type stream, so the security check that would normally reject the underlying php wrapper is not applied. StreamPlugin then opens the nested php://filter/... URI directly.
For comparison, the direct resource:
```smarty
{include file="php://filter/read=convert.base64-encode/resource=/tmp/secret.tpl"}
```
is blocked with stream 'php' not allowed by security setting.
Affected package:
smarty/smarty5.8.078d259d3b971c59a0cd719c270cc5cbb740c36a7v5.8.0Relevant code paths:
Smarty\Resource\BasePlugin::load(...)Smarty\Resource\StreamPlugin::getContent(...)Smarty\Security::isTrustedStream(...)BasePlugin::load() maps the built-in resource name stream directly to StreamPlugin before the code path that checks PHP stream wrappers with stream_get_wrappers() and Security::isTrustedStream($type). StreamPlugin::getContent() later calls fopen($filepath, 'r+') on the nested URI when the resource name contains ://.
Preconditions:
An application must render templates that are not fully trusted while relying on Smarty Security to restrict local files and PHP stream wrappers. The PoC sets:
```php
$smarty->enableSecurity();
$smarty->security_policy->streams = null;
```
Local reproduction:
The PoC creates a disposable template directory and a separate outside directory. It enables Smarty Security, disables all streams, and then compares three includes:
1. ../outside/secret.tpl to confirm the ordinary trusted-directory boundary is enforced.
2. php://filter/... to confirm direct PHP streams are blocked by Security::$streams = null.
3. stream:php://filter/... to show the built-in stream: resource bypasses the same restriction and reads the outside file.
Run:
```shell
php -d display_errors=1 poc.php
```
Observed sanitized output:
```text
package=smarty/smarty
installed_version=v5.8.0
template_dir=<tmp>/templates
outside_template=<tmp>/outside/secret.tpl
plain_dotdot_include=BLOCKED:Smarty\Exception:Smarty Security: not trusted file path '<tmp>/outside/secret.tpl'
direct_php_filter_include=BLOCKED:Smarty\Exception:stream 'php' not allowed by security setting
stream_php_filter_include=OK:U01BUlRZX1NUUkVBTV9XUkFQUEVSX1NFQ1VSSVRZX0VTQ0FQRQ==
expected_base64=U01BUlRZX1NUUkVBTV9XUkFQUEVSX1NFQ1VSSVRZX0VTQ0FQRQ==
```
The plain_dotdot_include line shows the directory boundary is enforced for ordinary traversal. The direct_php_filter_include line shows the same policy rejects php://filter when used directly. The stream_php_filter_include line shows that wrapping the same URI in Smarty's stream: resource bypasses that restriction and reads the outside file.
Impact:
A template author can bypass Smarty Security stream restrictions and read local files that are readable by the PHP process. With php://filter, file contents can be base64 encoded and rendered back through the template. This bypasses both the intended Security::$streams = null restriction and the normal trusted-template-directory check that blocks ../ traversal.
Duplicate checks:
Packagist/smarty/smarty version 5.8.0 returned no vulnerabilities.ecosystem=composer and affects=smarty/smarty returned historical Smarty advisories, including sandbox escapes, PHP code injection, XSS, and older path traversal issues. The listed path traversal advisories affect older versions and do not describe this current stream:php://filter resource-wrapper bypass in 5.8.0.smarty-php/smarty for stream:php://filter returned zero results.Smarty StreamPlugin php://filter and smarty/smarty isTrustedStream stream: did not identify a clear public duplicate during triage.Suggested remediation:
When resolving the built-in stream: resource, parse and validate the nested URI scheme before opening it. For example, stream:php://filter/... should call Security::isTrustedStream('php'), and Security::$streams = null should block the resource before StreamPlugin::getContent() reaches fopen().
It would also be safer for StreamPlugin to reject nested stream wrappers by default unless the underlying wrapper is explicitly allowed by the active security policy.
This issue can be reached over the network, attack complexity is low, an attacker needs administrative privileges on the target. No user interaction is required. Rated impact: confidentiality high, integrity none, availability none.
The score comes from this vector: CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
CVE-2026-62996 is classified as CWE-22: Path Traversal. A file path built from user input is not confined to the intended directory, letting an attacker reach files elsewhere on the filesystem.
CVE-2026-62996 is recorded against 2 packages.
Published on 7 August 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.
github.com (Web)
github.com (Web)
github.com (Web)
github.com (Package)
github.com (Web)
smarty/smarty has other advisories on record. If you are patching this one, these are worth checking on the same host:
These advisories are the same class of weakness (CWE-22: Path Traversal) in other software:
Details
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| smarty/smarty | 5.0.0 | 5.8.4 |
| unknown | — | — |
References
Similar Threats
Free Vulnerability Check
BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-62996 and other known CVE records.
Scan My Site Free →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.
Stay up to date with the latest from Boteraser.
We use cookies to improve your experience on our site. By using our site, you consent to cookies.
Manage your cookie preferences below:
Essential cookies enable basic functions and are necessary for the proper function of the website.
CloudFlare provides web performance and security solutions, enhancing site speed and protecting against threats.
Service URL: developers.cloudflare.com (opens in a new window)
These cookies are needed for adding comments on this website.
These cookies are used for managing login functionality on this website.
Statistics cookies collect information anonymously. This information helps us understand how visitors use our website.
Google Analytics is a powerful tool that tracks and analyzes website traffic for informed marketing decisions.
Service URL: policies.google.com (opens in a new window)
You can find more information in our Cookie Policy and Privacy Policy.