{html_image} already escaped alt and pass-through attributes, but emitted
file, path_prefix, href/link, width and height raw, letting an untrusted
value break out of the generated tag. Escape these at output time; the
unescaped values are still used for getimagesize()/DPI math. Escaping uses
htmlspecialchars with double_encode=false, so existing entities and values
like "100%" are preserved (no BC break for legitimate values).
{html_select_date} treated day_size/month_size/year_size as strings and
emitted them raw into size="…"; cast them to int to match
{html_select_time} and close the breakout.
The remaining flagged parameters (mailto extra; html_table *_attr/
trailpad/caption/loop; html_radios/html_checkboxes separator;
html_select_* *_extra/field_separator and the unrecognised-attribute
pass-through) intentionally emit raw markup as documented, so escaping
them would break backwards compatibility. Add a security note to those
docs pages instead, telling authors to escape untrusted values themselves.
Adds tests for html_image escaping (incl. benign-value/no-double-encode
checks) and the html_select_date size cast.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
{fetch} validates the requested URL with Security::isTrustedUri(), but
for non-http schemes (e.g. https) it reads the resource via
file_get_contents(), which follows redirects by default. An open redirect
on an otherwise trusted host could therefore be used to reach a
non-trusted, internal target, bypassing the trusted_uri policy (SSRF).
When a security policy is active, pass a stream context that disables
redirect-following (follow_location => 0, max_redirects => 1) to
file_get_contents() for remote resources. Behavior is unchanged when no
security policy is set, since there is no trusted_uri to bypass.
Adds a regression test using a custom stream wrapper that captures the
context {fetch} passes to file_get_contents, plus a backwards-compat test
for the no-security-policy case.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Security::_checkDir() validated file access using Smarty::_realpath(),
which only normalizes paths as strings and never follows symlinks. A
symlink placed inside a trusted secure_dir/template directory therefore
passed the trust check while file_get_contents() followed it to an
arbitrary file (e.g. /etc/passwd), affecting {include} and {fetch} of
local files.
Resolve the requested file with native realpath() and re-validate the
canonical, symlink-free path against the trusted directories. The trusted
directories are canonicalized the same way so legitimate symlinked
deployment paths (e.g. a Capistrano "current" release symlink, or macOS'
/var -> /private/var) keep working. Falls back to string normalization
only when the file does not yet exist on disk.
Adds regression tests covering both the rejected escape and an allowed
in-sandbox symlink, and documents the changelog convention in AGENTS.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Support for Laravel Collections style object chaining for objects return from function calls implemented as modifiers
Fixes#1151
* explain publishing docs
* Fixing forced OpCache Invalidation on every call, which is resulting in fast raising wasted memory
* Fix undefined $path variable warning
---------
Co-authored-by: Daniel Metzner <daniel.metzner@niceshops.com>
* Evolution of auto-escaping: no double-escaping when using the 'escape' modifier; add the 'force' mode to the 'escape' modifier; add the 'raw' modifier.
* Add 'raw' modifier's documentation
---------
Co-authored-by: Simon Wisselink <s.wisselink@iwink.nl>