Fix a security issue when an included sandboxed template has been loaded before without the sandbox context

This commit is contained in:
Fabien Potencier
2024-09-09 18:51:43 +02:00
parent 0887422319
commit 7afa198603
2 changed files with 42 additions and 7 deletions
+4 -7
View File
@@ -1569,13 +1569,6 @@ function twig_include(Environment $env, $context, $template, $variables = [], $w
if (!$alreadySandboxed = $sandbox->isSandboxed()) {
$sandbox->enableSandbox();
}
foreach ((\is_array($template) ? $template : [$template]) as $name) {
// if a Template instance is passed, it might have been instantiated outside of a sandbox, check security
if ($name instanceof TemplateWrapper || $name instanceof Template) {
$name->unwrap()->checkSecurity();
}
}
}
$loaded = null;
@@ -1604,6 +1597,10 @@ function twig_include(Environment $env, $context, $template, $variables = [], $w
}
try {
if ($isSandboxed && $loaded) {
$loaded->unwrap()->checkSecurity();
}
$ret = $loaded ? $loaded->render($variables) : '';
} catch (\Exception $e) {
if ($isSandboxed && !$alreadySandboxed) {
+38
View File
@@ -12,6 +12,10 @@ namespace Twig\Tests\Extension;
*/
use Twig\Environment;
use Twig\Extension\SandboxExtension;
use Twig\Loader\ArrayLoader;
use Twig\Sandbox\SecurityError;
use Twig\Sandbox\SecurityPolicy;
class CoreTest extends \PHPUnit\Framework\TestCase
{
@@ -283,6 +287,40 @@ class CoreTest extends \PHPUnit\Framework\TestCase
[[], new \ArrayIterator([1, 2]), 3],
];
}
public function testSandboxedInclude()
{
$twig = new Environment(new ArrayLoader([
'index' => '{{ include("included", sandboxed=true) }}',
'included' => '{{ "included"|e }}',
]));
$policy = new SecurityPolicy([], [], [], [], ['include']);
$sandbox = new SandboxExtension($policy, false);
$twig->addExtension($sandbox);
// We expect a compile error
$this->expectException(SecurityError::class);
$twig->render('index');
}
public function testSandboxedIncludeWithPreloadedTemplate()
{
$twig = new Environment(new ArrayLoader([
'index' => '{{ include("included", sandboxed=true) }}',
'included' => '{{ "included"|e }}',
]));
$policy = new SecurityPolicy([], [], [], [], ['include']);
$sandbox = new SandboxExtension($policy, false);
$twig->addExtension($sandbox);
// The template is loaded without the sandbox enabled
// so, no compile error
$twig->load('included');
// We expect a runtime error
$this->expectException(SecurityError::class);
$twig->render('index');
}
}
function foo_escaper_for_test(Environment $env, $string, $charset)