twigphp/Twig · error · SecurityNotAllowedTestError
Test " " is not allowed.
Error message
Test "%s" is not allowed.
What it means
checkSecurity() throws SecurityNotAllowedTestError when a template uses a Twig test (e.g. is odd, is defined) not in allowedTests. Before strict mode, unlisted tests only trigger a deprecation (they were historically always allowed in sandboxes); with strict mode enabled they throw immediately, matching planned 4.0 behavior.
Solutions
- Add the required tests to the policy: $policy->setAllowedTests([...]) or the constructor's $tests argument.
- Catch SecurityNotAllowedTestError around sandboxed rendering to identify the blocked test.
- Explicitly enumerate every test used by sandboxed templates when strict mode is on.
- Keep strict mode enabled in CI so missing test allowlist entries fail tests, not production.
Example fix
// before
$policy->setStrict(true); // template: {% if n is odd %}
// after
$policy->setAllowedTests(['odd', 'even', 'defined']);
$policy->setStrict(true); Defensive patterns
Strategy: try-catch
Validate before calling
foreach ($testsUsed as $t) {
if (!in_array($t, $allowedTests, true)) { /* update setAllowedTests */ }
} Try / catch
try {
$html = $twig->render($tpl, $ctx);
} catch (\Twig\Sandbox\SecurityNotAllowedTestError $e) {
$logger->warning('Sandbox blocked test', ['test' => $e->getTestName()]);
} Prevention
- List every Twig test used by sandboxed templates via setAllowedTests().
- Keep strict mode on in tests to replicate 4.0 behavior.
- Cover test usage in sandbox integration tests.
- Review 3.28 deprecation notices in logs as a checklist.
When it happens
Trigger: checkSecurity() called with $this->strict = true and a test absent from allowedTests (as exercised by testStrictModeCanBeEnabledViaSetterAfterConstruction, testStrictModeRejectsTestsViaSetter, testAllowedTestsCanBeUpdatedViaSetter); enabling strict mode via setStrict(true) then rendering a template that uses tests.
Common situations: Testing the Twig 3.28 deprecation/strict-mode transition for sandboxed tests; hardening a sandbox ahead of 4.0 where tests must be explicitly allowed.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Tag " " is not allowed.
- Filter " " is not allowed.
- Function " " is not allowed.
- Calling " " method on a " " object is not allowed.
- Calling " " property on a " " object is not allowed.
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/68cf3a949c59209b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Sandbox/SecurityPolicy.php:141
if (!\in_array($function, $this->allowedFunctions, true)) {
if (!$this->strict && 'parent' === $function) {
trigger_deprecation('twig/twig', '3.27', 'The "parent" function is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitly in your sandbox policy if needed (or enable strict mode on the security policy to opt-in to the 4.0 behavior now).');
} elseif (!$this->strict && 'block' === $function) {
trigger_deprecation('twig/twig', '3.27', 'The "block" function is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitly in your sandbox policy if needed (or enable strict mode on the security policy to opt-in to the 4.0 behavior now).');
} elseif (!$this->strict && 'attribute' === $function) {
trigger_deprecation('twig/twig', '3.27', 'The "attribute" function is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitly in your sandbox policy if needed (or enable strict mode on the security policy to opt-in to the 4.0 behavior now).');
} else {
throw new SecurityNotAllowedFunctionError(\sprintf('Function "%s" is not allowed.', $function), $function);
}
}
}
foreach ($tests as $test) {
if (!\in_array($test, $this->allowedTests, true)) {
if (!$this->strict) {
trigger_deprecation('twig/twig', '3.28', 'The "%s" test is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitly in your sandbox policy if needed (or enable strict mode on the security policy to opt-in to the 4.0 behavior now).', $test);
} else {
throw new SecurityNotAllowedTestError(\sprintf('Test "%s" is not allowed.', $test), $test);
}
}
}
}
public function checkMethodAllowed($obj, $method): void
{
if ($obj instanceof Template || $obj instanceof Markup) {
return;
}
$allowed = false;
$method = strtolower($method);
foreach ($this->allowedMethods as $class => $methods) {
if ($obj instanceof $class && \in_array($method, $methods, true)) {
$allowed = true;
break;
}View on GitHub (pinned to a414c3a491)