{"record":{"id":"f5fe3f838dcec3b2","repo":"twigphp/Twig","slug":"filter-s-is-not-allowed","errorCode":null,"errorMessage":"Filter \"%s\" is not allowed.","messagePattern":"Filter \"(.+?)\" is not allowed\\.","errorType":"exception","errorClass":"SecurityNotAllowedFilterError","httpStatus":null,"severity":"error","filePath":"src/Sandbox/SecurityPolicy.php","lineNumber":118,"sourceCode":"        if (\\func_num_args() < 4) {\n            trigger_deprecation('twig/twig', '3.28', 'Not passing the \"$tests\" argument to \"%s::checkSecurity()\" is deprecated; it will be required in 4.0.', static::class);\n        }\n\n        foreach ($tags as $tag) {\n            if (!\\in_array($tag, $this->allowedTags, true)) {\n                if (!$this->strict && 'extends' === $tag) {\n                    trigger_deprecation('twig/twig', '3.12', 'The \"extends\" tag 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).');\n                } elseif (!$this->strict && 'use' === $tag) {\n                    trigger_deprecation('twig/twig', '3.12', 'The \"use\" tag 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).');\n                } else {\n                    throw new SecurityNotAllowedTagError(\\sprintf('Tag \"%s\" is not allowed.', $tag), $tag);\n                }\n            }\n        }\n\n        foreach ($filters as $filter) {\n            if (!\\in_array($filter, $this->allowedFilters, true)) {\n                throw new SecurityNotAllowedFilterError(\\sprintf('Filter \"%s\" is not allowed.', $filter), $filter);\n            }\n        }\n\n        foreach ($functions as $function) {\n            if (!\\in_array($function, $this->allowedFunctions, true)) {\n                if (!$this->strict && 'parent' === $function) {\n                    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).');\n                } elseif (!$this->strict && 'block' === $function) {\n                    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).');\n                } elseif (!$this->strict && 'attribute' === $function) {\n                    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).');\n                } else {\n                    throw new SecurityNotAllowedFunctionError(\\sprintf('Function \"%s\" is not allowed.', $function), $function);\n                }\n            }\n        }\n\n        foreach ($tests as $test) {","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/Sandbox/SecurityPolicy.php#L100-L136","documentation":"checkSecurity() throws SecurityNotAllowedFilterError when a template applies a filter (e.g. |upper, |escape) that is not in allowedFilters. Unlike tags/functions, filters have no deprecation grace period: any non-allowlisted filter is rejected immediately.","triggerScenarios":"A sandboxed template uses a filter not passed to SecurityPolicy's $filters constructor argument nor added via setAllowedFilters(); test fixtures intentionally using banned filters.","commonSituations":"Adding new template logic that uses a filter the policy never allowed; copying a policy between projects with different filter sets; writing sandbox tests (testStrictMode*, testAllowedTestsCanBeUpdatedViaSetter) that assert rejection.","solutions":["Allow the filter: $policy->setAllowedFilters(array_merge($current, [$filter])) or include it in the constructor's $filters array.","Audit sandboxed templates (e.g. with a template lint) and align the policy with actually used filters.","Catch SecurityNotAllowedFilterError around load()/render() to surface the offending filter name to users.","Re-check the policy after upgrading Twig in case built-in filter usage changed."],"exampleFix":"// before\n $policy = new SecurityPolicy(['for'], [], [], [], []);\n // template uses {{ name|upper }}\n// after\n $policy = new SecurityPolicy(['for'], ['upper'], [], [], []);","handlingStrategy":"try-catch","validationCode":"if (!in_array($filter, $policy->getAllowedFilters(), true)) {\n    // template would throw; fix policy or template first\n}","typeGuard":null,"tryCatchPattern":"try {\n    $html = $sandboxTwig->load($name)->render($ctx);\n} catch (\\Twig\\Sandbox\\SecurityNotAllowedFilterError $e) {\n    $logger->warning('Sandbox blocked filter', ['filter' => $e->getFilterName()]);\n}","preventionTips":["Enumerate every filter used by sandboxed templates (grep for '|').","Update setAllowedFilters whenever templates gain new filters.","Re-run sandbox test suites after policy or template changes.","Differentiate dev (verbose catch + log) vs prod (deny + placeholder)."],"tags":["twig","sandbox","security-policy","filters"],"backgroundTag":"permission-denied","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}