mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-27 02:43:33 +00:00
8dd0383353
* 3.x: (23 commits)
Bump version
Prepare the 3.26.0 release
Update CHANGELOG
Document that the sandbox doesn't protect against resource exhaustion
Document template_from_string caveats when used in a sandboxed env
Pre-escape HTML input on the `spaceless` filter
Add docs on Markup about the goal of this class in the context of a sandbox
Fix sandbox bypass in the "column" filter
Fix sandbox `__toString` bypasses
Validate macro name in MacroReferenceExpression constructor
Fix sandbox bypass: PHP code injection via _self / import macro reference
Fix deprecations in tests
Fix sandbox bypass in the `{% sandbox %}` tag when including a preloaded template
Encode single quotes as \x27 in Compiler::string()
Fix sandbox bypass: PHP code injection via {% use %} template name
Fix unbounded memoisation of `IntlDateFormatter` / `NumberFormatter`
Fix deprecation
[Profiler] Escape template and profile names in HtmlDumper
Bump version
Fix sandbox bypass: propagate sandbox state to checkArrow for source-policy sandboxing
...
# Conflicts:
# CHANGELOG
# doc/filters/spaceless.rst
# extra/cssinliner-extra/CssInlinerExtension.php
# extra/inky-extra/InkyExtension.php
# extra/markdown-extra/MarkdownExtension.php
# src/Environment.php
# src/ExpressionParser/Infix/DotExpressionParser.php
# src/Extension/CoreExtension.php
# src/Node/Expression/FilterExpression.php
# src/Node/Expression/FunctionExpression.php
# src/Node/Expression/TestExpression.php
# src/Node/ModuleNode.php
# src/NodeVisitor/SandboxNodeVisitor.php
# src/Resources/core.php
# src/TokenParser/SandboxTokenParser.php
# tests/Extension/SandboxTest.php
114 lines
4.1 KiB
ReStructuredText
114 lines
4.1 KiB
ReStructuredText
Twig Sandbox
|
|
============
|
|
|
|
The ``sandbox`` extension can be used to evaluate untrusted code.
|
|
|
|
Registering the Sandbox
|
|
-----------------------
|
|
|
|
Register the ``SandboxExtension`` extension via the ``addExtension()`` method::
|
|
|
|
$twig->addExtension(new \Twig\Extension\SandboxExtension($policy));
|
|
|
|
Configuring the Sandbox Policy
|
|
------------------------------
|
|
|
|
The sandbox security is managed by a policy instance, which must be passed to
|
|
the ``SandboxExtension`` constructor.
|
|
|
|
By default, Twig comes with one policy class: ``\Twig\Sandbox\SecurityPolicy``.
|
|
This class allows you to allow-list some tags, filters, functions, and
|
|
properties and methods on objects::
|
|
|
|
$tags = ['if'];
|
|
$filters = ['upper'];
|
|
$methods = [
|
|
'Article' => ['getTitle', 'getBody'],
|
|
];
|
|
$properties = [
|
|
'Article' => ['title', 'body'],
|
|
];
|
|
$functions = ['range'];
|
|
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
|
|
|
|
With the above configuration, the security policy will only allow usage of the
|
|
``if`` tag, and the ``upper`` filter. Moreover, the templates will only be able
|
|
to call the ``getTitle()`` and ``getBody()`` methods on ``Article`` objects,
|
|
and the ``title`` and ``body`` public properties. Everything else won't be
|
|
allowed and will generate a ``\Twig\Sandbox\SecurityError`` exception.
|
|
|
|
.. note::
|
|
|
|
If the ``Article`` class implements the ``ArrayAccess`` interface, the
|
|
templates will only be able to access the ``title`` and ``body``
|
|
attributes.
|
|
|
|
Note that native array-like classes (like ``ArrayObject``) are always
|
|
allowed, you don't need to configure them.
|
|
|
|
Enabling the Sandbox
|
|
--------------------
|
|
|
|
By default, the sandbox mode is disabled and should be enabled when including
|
|
untrusted template code by using the ``sandboxed`` option of the ``include``
|
|
function:
|
|
|
|
.. code-block:: twig
|
|
|
|
{{ include('user.html.twig', sandboxed: true) }}
|
|
|
|
You can sandbox all templates by passing ``true`` as the second argument of
|
|
the extension constructor::
|
|
|
|
$twig->addExtension(new \Twig\Extension\SandboxExtension($policy, true));
|
|
|
|
Limiting Resource Usage
|
|
-----------------------
|
|
|
|
The sandbox prevents untrusted templates from reaching code, data, methods, or
|
|
properties they shouldn't. It does **not** prevent a template from consuming
|
|
CPU, memory, or wall-clock time, even under the strictest allow-list.
|
|
|
|
This is by design: any limit baked into Twig itself would be both arbitrary
|
|
and trivial to work around, since there are many ways a template can burn
|
|
resources (large ranges, nested loops, large string operations, recursive
|
|
macros, expensive filters, deeply nested includes, and so on).
|
|
|
|
If you render untrusted templates, you should contain them at the process level
|
|
rather than at the template engine level.
|
|
|
|
Accepting Callables Arguments
|
|
-----------------------------
|
|
|
|
The Twig sandbox allows you to configure which functions, filters, tests and
|
|
dot operations are allowed. Many of these calls can accept arguments. As these
|
|
arguments are not validated by the sandbox, you must be very careful.
|
|
|
|
For instance, accepting a PHP ``callable`` as an argument is dangerous as it
|
|
allows end user to call any PHP function (by passing a ``string``) or any
|
|
static methods (by passing an ``array``). For instance, it would accept any PHP
|
|
built-in functions like ``system()`` or ``exec()``::
|
|
|
|
$twig->addFilter(new \Twig\TwigFilter('custom', function (callable $callable) {
|
|
// ...
|
|
$callable();
|
|
// ...
|
|
}));
|
|
|
|
To avoid this security issue, don't type-hint such arguments with ``callable``
|
|
but use ``\Closure`` instead (not using a type-hint would also be problematic).
|
|
This restricts the allowed callables to PHP closures only, which is enough to
|
|
accept Twig arrow functions::
|
|
|
|
$twig->addFilter(new \Twig\TwigFilter('custom', function (\Closure $callable) {
|
|
// ...
|
|
$callable();
|
|
// ...
|
|
}));
|
|
|
|
{{ people|custom(p => p.username|join(', ') }}
|
|
|
|
Any PHP callable can easily be converted to a closure by using the `first-class callable syntax`_.
|
|
|
|
.. _`first-class callable syntax`: https://www.php.net/manual/en/functions.first_class_callable_syntax.php
|