La extensión sandbox se puede utilizar para evaluar código no confiable.
Registra la extensión SandboxExtension mediante el método addExtension():
$twig->addExtension(new \Twig\Extension\SandboxExtension($policy));
La seguridad del sandbox está gestionada por una instancia de política, que debe pasarse al constructor de SandboxExtension.
Por defecto, Twig viene con una clase de política: \Twig\Sandbox\SecurityPolicy. Esta clase te permite crear listas permitidas de algunas etiquetas, filtros, funciones, y propiedades y métodos en objetos:
$tags = ['if'];
$filters = ['upper'];
$methods = [
'Article' => ['getTitle', 'getBody'],
];
$properties = [
'Article' => ['title', 'body'],
];
$functions = ['range'];
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
Con la configuración anterior, la política de seguridad solo permitirá el uso de la etiqueta if y el filtro upper. Además, las plantillas solo podrán llamar a los métodos getTitle() y getBody() en objetos Article, y a las propiedades públicas title y body. Todo lo demás no estará permitido y generará una excepción \Twig\Sandbox\SecurityError.
Note
A partir de Twig 3.14.1 (y en Twig 3.11.2), si la clase Article implementa la interfaz ArrayAccess, las plantillas solo podrán acceder a los atributos title y body.
Ten en cuenta que las clases nativas similares a arrays (como ArrayObject) siempre están permitidas, no necesitas configurarlas.
Caution
Las etiquetas extends y use siempre están permitidas en una plantilla en sandbox. Ese comportamiento cambiará en la versión 4.0 donde estas etiquetas deberán ser explícitamente permitidas como cualquier otra etiqueta.
Por defecto, el modo sandbox está deshabilitado y debe habilitarse cuando se incluye código de plantilla no confiable usando la opción sandboxed de la función include:
{{ include('user.html.twig', sandboxed: true) }}
Puedes poner en sandbox todas las plantillas pasando true como segundo argumento del constructor de la extensión:
$twig->addExtension(new \Twig\Extension\SandboxExtension($policy, true));
El sandbox de Twig te permite configurar qué funciones, filtros, tests y operaciones de punto están permitidos. Muchas de estas llamadas pueden aceptar argumentos. Como estos argumentos no están validados por el sandbox, debes tener mucho cuidado.
Por ejemplo, aceptar un callable de PHP como argumento es peligroso ya que permite al usuario final llamar a cualquier función de PHP (pasando un string) o a cualquier método estático (pasando un array). Por ejemplo, aceptaría cualquier función incorporada de PHP como system() o exec():
$twig->addFilter(new \Twig\TwigFilter('custom', function (callable $callable) {
// ...
$callable();
// ...
}));
Para evitar este problema de seguridad, no uses callable como tipo de dato para tales argumentos, sino usa \Closure en su lugar (no usar un tipo de dato también sería problemático). Esto restringe los elementos invocables permitidos solo a closures de PHP, lo cual es suficiente para aceptar funciones flecha de Twig:
$twig->addFilter(new \Twig\TwigFilter('custom', function (\Closure $callable) {
// ...
$callable();
// ...
}));
{{ people|custom(p => p.username|join(', ')) }}
Cualquier elemento invocable de PHP se puede convertir fácilmente a un closure usando la sintaxis de elementos invocables de primera clase de PHP.