GHSA-7FXW-R6JV-74C8
Vulnerability from github – Published: 2026-05-21 21:28 – Updated: 2026-05-21 21:28Description
The fix for CVE-2024-45411 / GHSA-6j75-5wfj-gh66 added an explicit $loaded->unwrap()->checkSecurity() call in CoreExtension::include() so that a template already cached in Environment::$loadedTemplates is re-checked when included with sandboxed = true.
The deprecated but still functional {% sandbox %}{% include ... %}{% endsandbox %} tag path was not updated: it compiles to enableSandbox(); yield from $this->load(...)->unwrap()->yield(...); disableSandbox(); with no checkSecurity() re-invocation. If the included template was loaded once outside the sandbox in the same Environment instance, its constructor (and therefore its compiled checkSecurity() call) already ran while isSandboxed() was false, so the tags/filters/functions allowlist enforced by SecurityPolicy::checkSecurity() is never applied.
An attacker who can author the included template gains access to every filter, function and tag registered in the environment, regardless of the sandbox policy.
Resolution
The compiled output of {% sandbox %}{% include %} now calls checkSecurity() on the loaded template, matching the behaviour of CoreExtension::include() with sandboxed = true.
Credits
Twig would like to thank Claude Mythos Preview (via Project Glasswing) for reporting the issue and providing the fix.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "twig/twig"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.26.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-46638"
],
"database_specific": {
"cwe_ids": [
"CWE-693"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-21T21:28:28Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Description\n\nThe fix for CVE-2024-45411 / GHSA-6j75-5wfj-gh66 added an explicit `$loaded-\u003eunwrap()-\u003echeckSecurity()` call in `CoreExtension::include()` so that a template already cached in `Environment::$loadedTemplates` is re-checked when included with `sandboxed = true`.\n\nThe deprecated but still functional `{% sandbox %}{% include ... %}{% endsandbox %}` tag path was not updated: it compiles to `enableSandbox(); yield from $this-\u003eload(...)-\u003eunwrap()-\u003eyield(...); disableSandbox();` with no `checkSecurity()` re-invocation. If the included template was loaded once outside the sandbox in the same `Environment` instance, its constructor (and therefore its compiled `checkSecurity()` call) already ran while `isSandboxed()` was `false`, so the tags/filters/functions allowlist enforced by `SecurityPolicy::checkSecurity()` is never applied.\n\nAn attacker who can author the included template gains access to every filter, function and tag registered in the environment, regardless of the sandbox policy.\n\n### Resolution\n\nThe compiled output of `{% sandbox %}{% include %}` now calls `checkSecurity()` on the loaded template, matching the behaviour of `CoreExtension::include()` with `sandboxed = true`.\n\n### Credits\n\nTwig would like to thank Claude Mythos Preview (via Project Glasswing) for reporting the issue and providing the fix.",
"id": "GHSA-7fxw-r6jv-74c8",
"modified": "2026-05-21T21:28:28Z",
"published": "2026-05-21T21:28:28Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/twigphp/Twig/security/advisories/GHSA-7fxw-r6jv-74c8"
},
{
"type": "WEB",
"url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/twig/twig/CVE-2026-46638.yaml"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-6j75-5wfj-gh66"
},
{
"type": "PACKAGE",
"url": "https://github.com/twigphp/Twig"
},
{
"type": "WEB",
"url": "https://symfony.com/cve-2026-46638"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:H",
"type": "CVSS_V4"
}
],
"summary": "Twig: `{% sandbox %}{% include %}` skips checkSecurity() on cached templates (incomplete fix for CVE-2024-45411)"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.