CVE-2026-47732: twig/twig: sandbox bypass leaks render context

GHSA-pr2w-4gpj-cpq4 HIGH
Published June 5, 2026
CISO Take

A documented sandbox security policy bypass in Twig's template engine allows any user with template authoring access in a sandboxed environment to invoke PHP's `__toString()` on any object in the render context — regardless of what the SecurityPolicy explicitly blocks. With 5,225 downstream dependents and six prior CVEs in the same package, Twig is deeply embedded in PHP application stacks including AI-powered platforms built on Symfony; if those stacks pass LLM API credentials, database connections, or session objects into the render context, all of that data is within reach of a determined template author via a byte-by-byte comparison-operator oracle that requires no special filters to be allowlisted. No public exploit exists and the CVE is not in CISA KEV, but the advisory documents multiple confirmed bypass vectors in detail, substantially lowering the exploitation bar. Upgrade to twig/twig 3.26.0 immediately and, if patching is delayed, restrict sandbox template authoring to fully trusted internal users only.

Sources: GitHub Advisory NVD ATLAS

What is the risk?

HIGH. Exploitation requires existing template authoring access within a sandboxed Twig environment, which bounds the attack surface to authenticated or semi-trusted users — but once that bar is cleared, the sandbox security policy is completely circumvented with no further privileges required. The oracle exfiltration technique via comparison operators is stealthy, incremental, and leaves minimal log artifacts. The 5,225 downstream dependents create a wide blast radius across PHP-based AI application backends. The advisory documents bypass vectors comprehensively, and the six prior CVEs in this package suggest a pattern of sandbox-related weaknesses warranting heightened scrutiny.

How does the attack unfold?

Template Access
Attacker obtains template authoring access in a Twig-sandboxed multi-tenant environment, either through a legitimate account or by compromising an existing user account.
AML.T0012
Sandbox Bypass
Attacker crafts a template exploiting a documented bypass vector — such as the `is empty` test, loose comparison operators, or null-coalesce expressions — to force PHP string coercion on a Stringable context object without triggering SecurityPolicy validation.
AML.T0049
Oracle Exfiltration
Using comparison operators as a boolean oracle across repeated template renders, attacker recovers the string representation of sensitive context objects (API keys, DB credentials, tokens) byte by byte without any filters needing to be allowlisted.
AML.T0057
Credential Abuse
Attacker uses extracted LLM API keys or database credentials to access downstream AI services, exfiltrate stored conversations or training data, or pivot into broader infrastructure.
AML.T0106

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Anthropic Python composer <= 3.25.0 3.26.0
3.6K 5.2K dependents Pushed 3d ago 86% patched ~0d to patch Full package profile →

Do you use Anthropic Python? You're affected.

How severe is it?

CVSS 3.1
N/A
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
Moderate

What should I do?

6 steps
  1. Patch: upgrade twig/twig to >= 3.26.0 (composer require twig/twig:^3.26) and verify the version is deployed across all environments.

  2. Run composer audit to surface any other Twig-related advisories in the dependency tree.

  3. If patching is delayed, immediately restrict sandbox template authoring to fully trusted internal principals — disable any user-facing template editing capability.

  4. Audit your Twig render context: enumerate which objects (especially those holding credentials or secrets) are passed as template variables and minimize that surface.

  5. Review application logs for unusual template patterns involving comparison operators, is empty, null-coalesce, or do tags applied to service objects.

  6. Rotate any credentials that may have been exposed in template render contexts on multi-tenant instances.

How is it classified?

Which compliance frameworks are affected?

This CVE is relevant to:

EU AI Act
Article 9 - Risk management system
ISO 42001
6.1.2 - AI risk assessment
NIST AI RMF
MANAGE 2.2 - Mechanisms for addressing AI vulnerabilities
OWASP LLM Top 10
LLM05 - Supply Chain Vulnerabilities

Frequently Asked Questions

What is CVE-2026-47732?

A documented sandbox security policy bypass in Twig's template engine allows any user with template authoring access in a sandboxed environment to invoke PHP's `__toString()` on any object in the render context — regardless of what the SecurityPolicy explicitly blocks. With 5,225 downstream dependents and six prior CVEs in the same package, Twig is deeply embedded in PHP application stacks including AI-powered platforms built on Symfony; if those stacks pass LLM API credentials, database connections, or session objects into the render context, all of that data is within reach of a determined template author via a byte-by-byte comparison-operator oracle that requires no special filters to be allowlisted. No public exploit exists and the CVE is not in CISA KEV, but the advisory documents multiple confirmed bypass vectors in detail, substantially lowering the exploitation bar. Upgrade to twig/twig 3.26.0 immediately and, if patching is delayed, restrict sandbox template authoring to fully trusted internal users only.

Is CVE-2026-47732 actively exploited?

No confirmed active exploitation of CVE-2026-47732 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-47732?

1. Patch: upgrade twig/twig to >= 3.26.0 (`composer require twig/twig:^3.26`) and verify the version is deployed across all environments. 2. Run `composer audit` to surface any other Twig-related advisories in the dependency tree. 3. If patching is delayed, immediately restrict sandbox template authoring to fully trusted internal principals — disable any user-facing template editing capability. 4. Audit your Twig render context: enumerate which objects (especially those holding credentials or secrets) are passed as template variables and minimize that surface. 5. Review application logs for unusual template patterns involving comparison operators, `is empty`, null-coalesce, or `do` tags applied to service objects. 6. Rotate any credentials that may have been exposed in template render contexts on multi-tenant instances.

What systems are affected by CVE-2026-47732?

This vulnerability affects the following AI/ML architecture patterns: PHP-based AI application backends (Symfony/Twig), Multi-tenant SaaS with user-editable templates, AI report and document generation pipelines, Low-code AI automation platforms with template customization.

What is the CVSS score for CVE-2026-47732?

No CVSS score has been assigned yet.

What is the AI security impact?

Affected AI Architectures

PHP-based AI application backends (Symfony/Twig)Multi-tenant SaaS with user-editable templatesAI report and document generation pipelinesLow-code AI automation platforms with template customization

MITRE ATLAS Techniques

AML.T0010.001 AI Software
AML.T0049 Exploit Public-Facing Application
AML.T0057 LLM Data Leakage
AML.T0083 Credentials from AI Agent Configuration
AML.T0105 Escape to Host

Compliance Controls Affected

EU AI Act: Article 9
ISO 42001: 6.1.2
NIST AI RMF: MANAGE 2.2
OWASP LLM Top 10: LLM05

What are the technical details?

Original Advisory

### 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.

Exploitation Scenario

An adversary registers as a user on a multi-tenant AI platform that lets customers customize Twig-rendered report or email templates via a sandboxed editor. The SecurityPolicy blocks direct method calls on the database service object (which implements Stringable and whose string representation contains a connection URI with credentials), but the attacker crafts a template using `{% if dbService <= 'a' %}` — a loose comparison that coerces dbService to string without policy consultation. By iterating over character values in repeated template renders, the attacker recovers the full connection string character by character. With the extracted credentials, they pivot to the database, exfiltrate user data and stored LLM conversations, then use recovered API keys to abuse the platform's LLM quota for their own purposes.

Timeline

Published
June 5, 2026
Last Modified
June 5, 2026
First Seen
June 6, 2026

Related Vulnerabilities