Affected versions
Twig versions <=3.26.0 are affected by this security issue.
The issue has been fixed in Twig 3.27.0.
Description
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.