twigphp/Twig · error · LogicException

The sandbox requires a strict security policy, call…

Error message

The sandbox requires a strict security policy, call "setStrict(true)" on a dedicated policy for this sandbox.

What it means

Twig's Sandbox must be constructed with a strict security policy. If you pass a SecurityPolicy (the default policy implementation) whose isStrict() flag is false, the constructor rejects it with this LogicException, because non-strict policies do not provide the guarantees the sandbox relies on.

Solutions

  1. Call setStrict(true) on the SecurityPolicy before passing it to the Sandbox constructor.
  2. If a permissive policy is genuinely needed, do not use Sandbox; use sandbox checks (isSandbled/twig sandbox functions) with the policy directly via SandboxExtension.
  3. Verify no code path later flips strictness back off after construction.

Example fix

// before
$policy = new SecurityPolicy([], [], [], [], []);
$sandbox = new Sandbox($env, $policy); // throws

// after
$policy = new SecurityPolicy(['include'], [], [], [], []);
$policy->setStrict(true);
$sandbox = new Sandbox($env, $policy);
Defensive patterns

Strategy: validation

Validate before calling

$policy->setStrict(true);
if ($policy instanceof \Twig\Sandbox\SecurityPolicy && !$policy->isStrict()) {
    throw new \LogicException('Sandbox policy must be strict');
}

Try / catch

try { $sandbox = new \Twig\Sandbox\Sandbox($env, $policy); } catch (\LogicException $e) { if (str_contains($e->getMessage(), 'setStrict(true)')) { $policy->setStrict(true); $sandbox = new \Twig\Sandbox\Sandbox($env, $policy); } else { throw $e; } }

Prevention

When it happens

Trigger: new Sandbox($env, $policy) where $policy is a SecurityPolicy created without ->setStrict(true) (or after calling setStrict(false)), typically with allowed tags/filters/methods configured but strictness left at the default off.

Common situations: Setting up sandboxed template rendering for user-supplied templates and forgetting the setStrict(true) call; copying sandbox setup code from older Twig examples predating strictness requirements.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13). Data as JSON: /api/errors/1db6446a4954c451. Report an issue: GitHub.

Appendix: source

Thrown at src/Sandbox/Sandbox.php:37

 * Renders untrusted templates in a dedicated, always-sandboxed environment.
 *
 * The sandbox takes ownership of an environment crafted specifically for it:
 * its loader defines which templates are reachable, its extensions, filters,
 * functions, tests, and globals define which capabilities exist, and the
 * security policy defines what is allowed to execute. Never pass an
 * application environment: the sandbox environment must be dedicated to
 * rendering untrusted templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class Sandbox implements SandboxInterface
{
    public function __construct(
        private Environment $env,
        SecurityPolicyInterface $policy,
    ) {
        if ($policy instanceof SecurityPolicy && !$policy->isStrict()) {
            throw new \LogicException('The sandbox requires a strict security policy, call "setStrict(true)" on a dedicated policy for this sandbox.');
        }

        try {
            $env->addExtension(new SandboxExtension($policy, true));
        } catch (\LogicException $e) {
            throw new \LogicException(\sprintf('The environment passed to "%s" must be dedicated to it: pass a freshly built environment that has no "%s" registered and has not been used yet.', self::class, SandboxExtension::class), 0, $e);
        }
    }

    public function render(string $name, array $context = []): string
    {
        return $this->env->render($name, $context);
    }

    public function display(string $name, array $context = []): void
    {
        $this->env->display($name, $context);
    }

View on GitHub (pinned to a414c3a491)