Sandbox

Sandbox provides a security layer that gives you control over which tags, PHP functions, methods, etc. can be used in templates. Thanks to the sandbox mode, you can safely collaborate with a client or external coder on template creation without worrying about compromising the application or unwanted operations.

How does it work? We simply define what we want to allow in the template. In the beginning, everything is forbidden and we gradually grant permissions. The following code allows the the template to use the {block}, {if}, {else} and {=} tags (the latter is a tag for printing a variable or expression) and all filters:

$policy = new Latte\Sandbox\SecurityPolicy;
$policy->allowTags(['block', 'if', 'else', '=']);
$policy->allowFilters($policy::All);

$latte->setPolicy($policy);

We can also allow access to global functions, methods or properties of objects:

$policy->allowFunctions(['trim', 'strlen']);
$policy->allowMethods(Nette\Security\User::class, ['isLoggedIn', 'isAllowed']);
$policy->allowProperties(Nette\Database\Row::class, $policy::All);

Isn't that amazing? You can control everything at a very low level. If the template tries to call an unauthorized function or access an unauthorized method or property, it throws exception Latte\SecurityViolationException.

Creating policies from scratch, when everything is forbidden, may not be convenient, so you can start from a safe foundation:

$policy = Latte\Sandbox\SecurityPolicy::createSafePolicy();

This means that all standard tags are allowed except for contentType, debugbreak, dump, extends, import, include, layout, php, sandbox, snippet, snippetArea, templatePrint, varPrint, widget. All standard filters are allowed as well except for datastream, noescape and nocheck. Finally, access to the methods and properties of object $iterator is allowed too.

The rules apply to the template that we insert with the new {sandbox} tag. Which is a something like {include}, but it turns on sandbox mode and also doesn't pass any external variables:

{sandbox 'untrusted.latte'}

Thus, the layout and individual pages can use all tags and variables as before, restrictions will be applied only to the template untrusted.latte.

Some violations, such as the use of a forbidden tag or filter, are detected at compile time. Others, such as calling unallowed methods of an object, at runtime. The template can also contain any other bugs. In order to prevent an exception from throwing from the sandboxed template, which disrupts the entire rendering, you can define your own exception handler, which, for example, just logs it.

If we want to turn on sandbox mode directly for all templates, it's easy:

$latte->setSandboxMode();

To ensure that a user doesn't insert PHP code into the page that is syntactically correct but forbidden and causes a PHP Compile Error, we recommend having templates checked by the PHP linter. You can activate this functionality using the Engine::enablePhpLint() method. Since it needs to call the PHP binary for the check, pass its path as a parameter:

$latte = new Latte\Engine;
$latte->enablePhpLinter('/path/to/php');
version: 3.0