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 10:51:06 +02:00
parent e80fb8ebba
commit 41103dcdc2
2 changed files with 43 additions and 7 deletions
+4 -7
View File
@@ -1400,13 +1400,6 @@ final class CoreExtension extends AbstractExtension
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();
}
}
}
try {
@@ -1419,6 +1412,10 @@ final class CoreExtension extends AbstractExtension
}
}
if ($isSandboxed && $loaded) {
$loaded->unwrap()->checkSecurity();
}
return $loaded ? $loaded->render($variables) : '';
} finally {
if ($isSandboxed && !$alreadySandboxed) {
+39
View File
@@ -12,8 +12,13 @@ namespace Twig\Tests\Extension;
*/
use PHPUnit\Framework\TestCase;
use Twig\Environment;
use Twig\Error\RuntimeError;
use Twig\Extension\CoreExtension;
use Twig\Extension\SandboxExtension;
use Twig\Loader\ArrayLoader;
use Twig\Sandbox\SecurityError;
use Twig\Sandbox\SecurityPolicy;
class CoreTest extends TestCase
{
@@ -313,6 +318,40 @@ class CoreTest extends TestCase
[1, 42, "\x00\x34\x32"],
];
}
public function testSandboxedInclude()
{
$twig = new Environment(new ArrayLoader([
'index' => '{{ include("included", sandboxed=true) }}',
'included' => '{{ "included"|e }}',
]));
$policy = new SecurityPolicy(allowedFunctions: ['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(allowedFunctions: ['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');
}
}
final class CoreTestIteratorAggregate implements \IteratorAggregate