Skip to content

Commit 41103dc

Browse files
committed
Fix a security issue when an included sandboxed template has been loaded before without the sandbox context
1 parent e80fb8e commit 41103dc

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

src/Extension/CoreExtension.php

+4-7
Original file line numberDiff line numberDiff line change
@@ -1400,13 +1400,6 @@ public static function include(Environment $env, $context, $template, $variables
14001400
if (!$alreadySandboxed = $sandbox->isSandboxed()) {
14011401
$sandbox->enableSandbox();
14021402
}
1403-
1404-
foreach ((\is_array($template) ? $template : [$template]) as $name) {
1405-
// if a Template instance is passed, it might have been instantiated outside of a sandbox, check security
1406-
if ($name instanceof TemplateWrapper || $name instanceof Template) {
1407-
$name->unwrap()->checkSecurity();
1408-
}
1409-
}
14101403
}
14111404

14121405
try {
@@ -1419,6 +1412,10 @@ public static function include(Environment $env, $context, $template, $variables
14191412
}
14201413
}
14211414

1415+
if ($isSandboxed && $loaded) {
1416+
$loaded->unwrap()->checkSecurity();
1417+
}
1418+
14221419
return $loaded ? $loaded->render($variables) : '';
14231420
} finally {
14241421
if ($isSandboxed && !$alreadySandboxed) {

tests/Extension/CoreTest.php

+39
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@
1212
*/
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Twig\Environment;
1516
use Twig\Error\RuntimeError;
1617
use Twig\Extension\CoreExtension;
18+
use Twig\Extension\SandboxExtension;
19+
use Twig\Loader\ArrayLoader;
20+
use Twig\Sandbox\SecurityError;
21+
use Twig\Sandbox\SecurityPolicy;
1722

1823
class CoreTest extends TestCase
1924
{
@@ -313,6 +318,40 @@ public function provideCompareCases()
313318
[1, 42, "\x00\x34\x32"],
314319
];
315320
}
321+
322+
public function testSandboxedInclude()
323+
{
324+
$twig = new Environment(new ArrayLoader([
325+
'index' => '{{ include("included", sandboxed=true) }}',
326+
'included' => '{{ "included"|e }}',
327+
]));
328+
$policy = new SecurityPolicy(allowedFunctions: ['include']);
329+
$sandbox = new SandboxExtension($policy, false);
330+
$twig->addExtension($sandbox);
331+
332+
// We expect a compile error
333+
$this->expectException(SecurityError::class);
334+
$twig->render('index');
335+
}
336+
337+
public function testSandboxedIncludeWithPreloadedTemplate()
338+
{
339+
$twig = new Environment(new ArrayLoader([
340+
'index' => '{{ include("included", sandboxed=true) }}',
341+
'included' => '{{ "included"|e }}',
342+
]));
343+
$policy = new SecurityPolicy(allowedFunctions: ['include']);
344+
$sandbox = new SandboxExtension($policy, false);
345+
$twig->addExtension($sandbox);
346+
347+
// The template is loaded without the sandbox enabled
348+
// so, no compile error
349+
$twig->load('included');
350+
351+
// We expect a runtime error
352+
$this->expectException(SecurityError::class);
353+
$twig->render('index');
354+
}
316355
}
317356

318357
final class CoreTestIteratorAggregate implements \IteratorAggregate

0 commit comments

Comments
 (0)