Skip to main content

Twig CVE-2026-46634

HIGH
Protection Mechanism Failure (CWE-693)
2026-05-21 https://github.com/twigphp/Twig GHSA-24x9-r6q4-q93w
7.7
CVSS 4.0 · Vendor: https://github.com/twigphp/Twig
Share

Severity by source

Vendor (https://github.com/twigphp/Twig) PRIMARY
7.7 HIGH
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Primary rating from Vendor (https://github.com/twigphp/Twig) · only source for this CVE.

CVSS VectorVendor: https://github.com/twigphp/Twig

CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
X

Lifecycle Timeline

4
Re-analysis Queued
Jul 14, 2026 - 22:22 vuln.today
cvss_changed
CVSS changed
Jul 14, 2026 - 22:22 NVD
7.7 (HIGH)
Source Code Evidence Fetched
May 21, 2026 - 22:03 vuln.today
Analysis Generated
May 21, 2026 - 22:03 vuln.today

DescriptionCVE.org

Description

When the sandbox is enabled selectively via SourcePolicyInterface (and not globally), a sandboxed template that is allowed to call template_from_string and include can render an arbitrary inner template with no security policy enforcement.

Environment::createTemplate() compiles the inner string under a synthesized name (__string_template__<hash>), so a name/path-based SourcePolicy returns false for it, and the inner template's checkSecurity() becomes a no-op. From a template the integrator believes is sandboxed, an attacker can use any tag/filter/function (including constant() to read secrets, or |map("system") to execute shell commands).

Resolution

This is a configuration trap rather than a code bug: there is no legitimate use case for exposing template_from_string to untrusted template authors, and propagating the parent sandbox state through template_from_string would require invasive changes to SourcePolicyInterface semantics with their own risks.

Starting with Twig 3.26.0, the documentation and the PHPDoc of StringLoaderExtension::templateFromString() explicitly warn against allowing template_from_string in a sandboxed environment (i.e. listing it in a SecurityPolicy allowed-functions list). Integrators using a SourcePolicyInterface MUST NOT allow template_from_string in their allowed functions; the safest option is not to register StringLoaderExtension at all when a sandbox is in use.

Credits

Twig would like to thank Claude Mythos Preview (via Project Glasswing) for reporting the issue.

AnalysisAI

Sandbox escape in Twig 3.9.0-3.25.x allows any attacker with template authoring access to fully bypass SourcePolicyInterface-driven security policies, enabling OS command execution via |map("system") and secret disclosure via constant(). The bypass occurs because Environment::createTemplate() compiles inline strings under a synthesized name (__string_template__<hash>) that name/path-based SourcePolicy implementations do not recognize, causing checkSecurity() to silently become a no-op on the inner template. No public exploit has been identified at time of analysis, though the vendor advisory provides sufficient technical detail for reproduction, and the RCE tag confirms the potential impact is critical for affected configurations.

Technical ContextAI

Twig is a widely used PHP templating engine (composer package twig/twig). Its sandbox mechanism has two modes: global (all templates sandboxed uniformly via SandboxExtension) and selective (per-source, via SourcePolicyInterface, where only templates originating from specific paths or names are subject to security policy). The StringLoaderExtension provides the template_from_string Twig function, which calls Environment::createTemplate() to compile an inline string as a template at runtime. The root cause, classified as CWE-693 (Protection Mechanism Failure), is that createTemplate() assigns the synthesized name __string_template__<hash> to the resulting template object. When a SourcePolicy implementation checks whether to sandbox this name, it returns false because the hash-based name matches no known source path or identifier - causing the sandbox to treat the inner template as unsandboxed. The checkSecurity() gate is never invoked, so all restrictions on tags, filters, and functions are bypassed for that inner template context.

RemediationAI

The primary fix is to upgrade to Twig 3.26.0, which introduces explicit documentation and PHPDoc warnings in StringLoaderExtension::templateFromString() making the unsafe combination unmistakable to integrators; vendor advisory: https://github.com/twigphp/Twig/security/advisories/GHSA-24x9-r6q4-q93w. If an immediate upgrade is not possible, remove template_from_string from the SecurityPolicy allowed-functions list - the vendor explicitly states there is no legitimate use case for exposing this function to untrusted template authors, so removal has no functional downside for sandboxed contexts. The most robust compensating control is to unregister StringLoaderExtension entirely when using SourcePolicyInterface-based sandboxing, eliminating the attack surface at the extension registration level. Integrators using global sandbox mode require no action.

Share

CVE-2026-46634 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy