CVE-2026-47732: Twig Sandbox: multiple `__toString()` policy bypasses via unguarded string coercion points
Description
SandboxNodeVisitor enforces SecurityPolicy::checkMethodAllowed() for implicit toString() calls by wrapping selected AST nodes in CheckToStringNode. The set of wrapped nodes is incomplete, and several Twig language constructs still trigger PHP string coercion on a Stringable operand without first consulting the policy. A sandboxed template author can therefore invoke toString() on any object reachable in the render context, even when toString on its class is not allowlisted.
Confirmed bypass vectors:
- Conditional expressions (a ? b : c, a ?: b, a ?? b) used as the input of a string-coercing filter or as a filter/function argument. - The matches operator and the loose comparison operators (==, !=, <, >, <=, >=, <=>), which coerce a Stringable operand to string and can be used as an oracle to recover the value byte by byte (no tag, filter or function needs to be allowlisted). - Twig tests in general (which were never policy-gated), in particular is empty which casts a Stringable value via (string) $value in CoreExtension::testEmpty(). - Null-coalesce expressions nested in concatenation, and the direct output of allowed functions or filters that return a Stringable object. - Arguments passed to allowed object methods, template-name expressions of template-loading tags (include, extends, use, ...), dynamic attribute/property names, and spread arguments from Traversable objects. - The do tag and the .. range operator.
Resolution
The sandbox now wraps every child node that the parent will string-coerce at runtime, instead of relying on a hardcoded list of node types in SandboxNodeVisitor. A new Twig\Node\CoercesChildrenToStringInterface lets nodes declare which of their children must be guarded; core nodes (concatenation, comparison and range binaries, filter/function/test expressions, do, include, extends, use, ...) implement it. Spread arguments are materialised and policy-checked via the new SandboxExtension::ensureSpreadAllowed(), and dynamic attribute names are checked at runtime inside CoreExtension::getAttribute().
Credits
Twig would like to thank Anthropic Glasswing and El Kharoubi Iosif for reporting the issues, and Fabien Potencier for providing the fixes.
Other sources
Twig is a template language for PHP. Prior to 3.26.0, several Twig language constructs trigger PHP string coercion on a Stringable operand without consulting SecurityPolicy::checkMethodAllowed(), allowing a sandboxed template author to invoke toString() on objects reachable in the render context through conditional expressions, comparison operators, tests, template-loading tags, dynamic attribute names, spread arguments, the do tag, and the .. range operator. This issue is fixed in version 3.26.0.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
composer/twig/twigto a version that resolves this vulnerability.Fixed in 3.26.0 - Upgrade
Upgrade to a fixed release to a version that resolves this vulnerability.
Fixed in 3.26.0Patch Twig Sandbox: multiple `__toString()` policy bypasses via unguarded string coercion points
Event History
Frequently Asked Questions
What is the severity of CVE-2026-47732?
CVE-2026-47732 has a risk rating of 65.
What software is affected by CVE-2026-47732?
CVE-2026-47732 affects the Composer Twig library.
How do I fix CVE-2026-47732?
To fix CVE-2026-47732, update to the latest version of the Twig library.
What type of vulnerability is CVE-2026-47732 classified as?
CVE-2026-47732 is classified as an Input Validation vulnerability.
When was CVE-2026-47732 published?
CVE-2026-47732 was published on June 5, 2026.