GHSA-P42Q-9PRX-Q5WQ
Vulnerability from github – Published: 2026-06-30 18:41 – Updated: 2026-06-30 18:41Description
The 3.26.0 source-policy hardening changed the signature of CoreExtension::checkArrow() to take a boolean $isSandboxed instead of an Environment, and added the same $isSandboxed argument to CoreExtension::arraySome() and CoreExtension::arrayEvery(). Compiled templates were updated to pass the per-source sandbox state computed at the call site.
The deprecated internal wrappers exposed in src/Resources/core.php for legacy third-party code (twig_check_arrow_in_sandbox(), twig_array_some(), twig_array_every()) were not updated:
twig_array_some()andtwig_array_every()callCoreExtension::arraySome()/arrayEvery()without forwarding the sandbox state. The underlying methods default$isSandboxedtofalse, so the callable-must-be-a-Closurerestriction is silently bypassed in sandbox mode and a string callable such as'strcmp'is accepted.twig_check_arrow_in_sandbox()passes theEnvironmentobject whereCoreExtension::checkArrow()now expects abool, which throws aTypeErroron PHP 8+.
Compiled Twig templates are not affected: they call CoreExtension::* directly with the correct arguments. Applications are only impacted if they still call the deprecated twig_* helpers on top of a sandboxed Environment.
Resolution
The three wrappers now resolve the current sandbox state via twig_resolve_is_sandboxed() (the same helper compiled templates use), and forward it to the corresponding CoreExtension::* method. twig_check_arrow_in_sandbox() no longer triggers a TypeError, and twig_array_some() / twig_array_every() now enforce the same sandbox restriction as compiled templates.
Credits
We would like to thank El Kharoubi Iosif for reporting the issue and Fabien Potencier for providing the fix.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.26.0"
},
"package": {
"ecosystem": "Packagist",
"name": "twig/twig"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.27.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-48805"
],
"database_specific": {
"cwe_ids": [
"CWE-693"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-30T18:41:30Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "### Description\n\nThe 3.26.0 source-policy hardening changed the signature of `CoreExtension::checkArrow()` to take a boolean `$isSandboxed` instead of an `Environment`, and added the same `$isSandboxed` argument to `CoreExtension::arraySome()` and `CoreExtension::arrayEvery()`. Compiled templates were updated to pass the per-source sandbox state computed at the call site.\n\nThe deprecated internal wrappers exposed in `src/Resources/core.php` for legacy third-party code (`twig_check_arrow_in_sandbox()`, `twig_array_some()`, `twig_array_every()`) were not updated:\n\n- `twig_array_some()` and `twig_array_every()` call `CoreExtension::arraySome()` / `arrayEvery()` without forwarding the sandbox state. The underlying methods default `$isSandboxed` to `false`, so the callable-must-be-a-`Closure` restriction is silently bypassed in sandbox mode and a string callable such as `\u0027strcmp\u0027` is accepted.\n- `twig_check_arrow_in_sandbox()` passes the `Environment` object where `CoreExtension::checkArrow()` now expects a `bool`, which throws a `TypeError` on PHP 8+.\n\nCompiled Twig templates are not affected: they call `CoreExtension::*` directly with the correct arguments. Applications are only impacted if they still call the deprecated `twig_*` helpers on top of a sandboxed `Environment`.\n\n### Resolution\n\nThe three wrappers now resolve the current sandbox state via `twig_resolve_is_sandboxed()` (the same helper compiled templates use), and forward it to the corresponding `CoreExtension::*` method. `twig_check_arrow_in_sandbox()` no longer triggers a `TypeError`, and `twig_array_some()` / `twig_array_every()` now enforce the same sandbox restriction as compiled templates.\n\n### Credits\n\nWe would like to thank El Kharoubi Iosif for reporting the issue and Fabien Potencier for providing the fix.",
"id": "GHSA-p42q-9prx-q5wq",
"modified": "2026-06-30T18:41:30Z",
"published": "2026-06-30T18:41:30Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/twigphp/Twig/security/advisories/GHSA-p42q-9prx-q5wq"
},
{
"type": "WEB",
"url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/twig/twig/CVE-2026-48805.yaml"
},
{
"type": "PACKAGE",
"url": "https://github.com/twigphp/Twig"
},
{
"type": "WEB",
"url": "https://github.com/twigphp/Twig/releases/tag/v3.27.0"
},
{
"type": "WEB",
"url": "https://symfony.com/blog/cve-2026-48805-sandbox-state-regression-in-deprecated-internal-wrappers-in-src-resources-core-php"
}
],
"schema_version": "1.4.0",
"severity": [],
"summary": "Twig: Sandbox state regression in deprecated internal wrappers in `src/Resources/core.php`"
}
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.