Summary
Twig's template sandbox can incorrectly reuse cached allow-list decisions across renders, even after the sandbox policy has changed.
In deployments that rely on Twig's sandbox for isolation, this may allow a template rendered under a stricter policy to behave as if a looser or empty policy were still in effect, enabling access to disallowed filters, tags, or functions.
Twig's template sandbox can incorrectly reuse cached allow-list decisions across renders, even after the sandbox policy has changed.
In deployments that rely on Twig's sandbox for isolation, this may allow a template rendered under a stricter policy to behave as if a looser or empty policy were still in effect, enabling access to disallowed filters, tags, or functions.
Affected context
This vulnerability appears in PHP applications that use Twig's sandbox feature to restrict what templates are allowed to do, especially in scenarios where template content is user-supplied or multi-tenant.
It is relevant when sandbox policies (such as allowed filters, tags, or functions) can change between template renders, for example across different users, roles, or environments.
Under these conditions, a previously constructed Template instance may keep a cached verdict that no longer matches the current sandbox policy, weakening expected isolation.
This vulnerability appears in PHP applications that use Twig's sandbox feature to restrict what templates are allowed to do, especially in scenarios where template content is user-supplied or multi-tenant.
It is relevant when sandbox policies (such as allowed filters, tags, or functions) can change between template renders, for example across different users, roles, or environments.
Under these conditions, a previously constructed Template instance may keep a cached verdict that no longer matches the current sandbox policy, weakening expected isolation.
Exploit preconditions
- Attack surface: Template rendering paths that use Twig's sandbox for untrusted or semi-trusted templates
- Required access: Ability to influence which templates are rendered and/or provide template content executed within the sandbox
- Trigger point: Rendering a template after the sandbox policy has changed, while the Template instance still holds cached allow-list decisions from an earlier policy
- Why exploitation is possible: The sandbox's per-template verdict about allowed tags, filters, and functions is computed at Template construction and may not be recomputed on later renders, causing the engine to apply outdated, potentially broader permissions.
- Attack surface: Template rendering paths that use Twig's sandbox for untrusted or semi-trusted templates
- Required access: Ability to influence which templates are rendered and/or provide template content executed within the sandbox
- Trigger point: Rendering a template after the sandbox policy has changed, while the Template instance still holds cached allow-list decisions from an earlier policy
- Why exploitation is possible: The sandbox's per-template verdict about allowed tags, filters, and functions is computed at Template construction and may not be recomputed on later renders, causing the engine to apply outdated, potentially broader permissions.
Why this happens
The underlying issue is improper enforcement of security policies due to stateful caching in the sandbox mechanism.
Twig computes and caches per-template allow-list decisions when a Template object is instantiated, but the cache can persist across subsequent renders even when the sandbox policy changes.
This corresponds to CWE-693: Protection Mechanism Failure, and is closely related to authorization flaws like CWE-863, because templates can execute operations that should be disallowed under the current policy.
Conceptually, the sandbox trusts stale authorization state instead of reevaluating policies per render, breaking isolation guarantees.
The underlying issue is improper enforcement of security policies due to stateful caching in the sandbox mechanism.
Twig computes and caches per-template allow-list decisions when a Template object is instantiated, but the cache can persist across subsequent renders even when the sandbox policy changes.
This corresponds to CWE-693: Protection Mechanism Failure, and is closely related to authorization flaws like CWE-863, because templates can execute operations that should be disallowed under the current policy.
Conceptually, the sandbox trusts stale authorization state instead of reevaluating policies per render, breaking isolation guarantees.
Potential impact
- Templates may call filters, tags, or functions that are supposed to be disallowed under the current sandbox policy
- Sandbox escapes that can lead to data exposure or manipulation beyond the intended template scope
- Unauthorized access to application services exposed via Twig functions (e.g., helpers that touch the filesystem, environment, or sensitive data)
- Elevation of capabilities between tenants or user roles that rely on per-render sandbox restrictions
- Templates may call filters, tags, or functions that are supposed to be disallowed under the current sandbox policy
- Sandbox escapes that can lead to data exposure or manipulation beyond the intended template scope
- Unauthorized access to application services exposed via Twig functions (e.g., helpers that touch the filesystem, environment, or sensitive data)
- Elevation of capabilities between tenants or user roles that rely on per-render sandbox restrictions
General mitigation guidance
Effective mitigation focuses on making sandbox enforcement policy-consistent per render and reducing trust in cached authorization decisions.
Recommended high-level patterns include:
- Design template sandboxing so that allow-list decisions are evaluated against the current policy for each render, avoiding long-lived caches that span different security contexts.
- Treat sandbox policy as part of the request's security context and ensure that any reusable template objects derive permissions from that context afresh.
- Avoid mixing templates for different tenants or roles within the same caching layer unless sandbox rules are identical and immutable.
- Restrict what Twig functions, tags, and filters expose; default to minimal capabilities so that even if sandbox rules weaken, templates cannot reach powerful operations.
- Use strict configuration patterns where untrusted templates are isolated from core application state, limiting the blast radius of any sandbox enforcement failure.
Effective mitigation focuses on making sandbox enforcement policy-consistent per render and reducing trust in cached authorization decisions.
Recommended high-level patterns include:
- Design template sandboxing so that allow-list decisions are evaluated against the current policy for each render, avoiding long-lived caches that span different security contexts.
- Treat sandbox policy as part of the request's security context and ensure that any reusable template objects derive permissions from that context afresh.
- Avoid mixing templates for different tenants or roles within the same caching layer unless sandbox rules are identical and immutable.
- Restrict what Twig functions, tags, and filters expose; default to minimal capabilities so that even if sandbox rules weaken, templates cannot reach powerful operations.
- Use strict configuration patterns where untrusted templates are isolated from core application state, limiting the blast radius of any sandbox enforcement failure.
How teams detect issues like this
Detection typically relies on analyzing how sandbox policies and template instances interact over time:
- Static analysis and configuration review: Examine Twig integration code to identify where sandbox policies can change per user or per render while Template instances are reused or cached. Flag patterns where authorization is computed at construction rather than on each render.
- Code review signals: Look for long-lived template caches, shared template pools across tenants, or policy objects that are mutable at runtime without corresponding reevaluation in the render path.
- Runtime monitoring: Instrument template rendering to record which filters, tags, and functions are invoked under each sandbox policy and alert on violations of declared allow-lists.
- Policy enforcement tooling: Use automated security checks in CI that validate sandbox configurations against organizational rules (for example, ensuring that untrusted templates can only access a constrained set of functions).
Detection typically relies on analyzing how sandbox policies and template instances interact over time:
- Static analysis and configuration review: Examine Twig integration code to identify where sandbox policies can change per user or per render while Template instances are reused or cached. Flag patterns where authorization is computed at construction rather than on each render.
- Code review signals: Look for long-lived template caches, shared template pools across tenants, or policy objects that are mutable at runtime without corresponding reevaluation in the render path.
- Runtime monitoring: Instrument template rendering to record which filters, tags, and functions are invoked under each sandbox policy and alert on violations of declared allow-lists.
- Policy enforcement tooling: Use automated security checks in CI that validate sandbox configurations against organizational rules (for example, ensuring that untrusted templates can only access a constrained set of functions).

