Skip to content

Commit 11f68e2

Browse files
committedSep 9, 2024··
Fix a security issue when an included sandboxed template has been loaded before without the sandbox context
1 parent 540b54e commit 11f68e2

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
@@ -1431,13 +1431,6 @@ public static function include(Environment $env, $context, $template, $variables
14311431
if (!$alreadySandboxed = $sandbox->isSandboxed()) {
14321432
$sandbox->enableSandbox();
14331433
}
1434-
1435-
foreach ((\is_array($template) ? $template : [$template]) as $name) {
1436-
// if a Template instance is passed, it might have been instantiated outside of a sandbox, check security
1437-
if ($name instanceof TemplateWrapper || $name instanceof Template) {
1438-
$name->unwrap()->checkSecurity();
1439-
}
1440-
}
14411434
}
14421435

14431436
try {
@@ -1452,6 +1445,10 @@ public static function include(Environment $env, $context, $template, $variables
14521445
return '';
14531446
}
14541447

1448+
if ($isSandboxed) {
1449+
$loaded->unwrap()->checkSecurity();
1450+
}
1451+
14551452
return $loaded->render($variables);
14561453
} finally {
14571454
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
{
@@ -354,6 +359,40 @@ public static function provideCompareCases()
354359
[1, 42, "\x00\x34\x32"],
355360
];
356361
}
362+
363+
public function testSandboxedInclude()
364+
{
365+
$twig = new Environment(new ArrayLoader([
366+
'index' => '{{ include("included", sandboxed: true) }}',
367+
'included' => '{{ "included"|e }}',
368+
]));
369+
$policy = new SecurityPolicy(allowedFunctions: ['include']);
370+
$sandbox = new SandboxExtension($policy, false);
371+
$twig->addExtension($sandbox);
372+
373+
// We expect a compile error
374+
$this->expectException(SecurityError::class);
375+
$twig->render('index');
376+
}
377+
378+
public function testSandboxedIncludeWithPreloadedTemplate()
379+
{
380+
$twig = new Environment(new ArrayLoader([
381+
'index' => '{{ include("included", sandboxed: true) }}',
382+
'included' => '{{ "included"|e }}',
383+
]));
384+
$policy = new SecurityPolicy(allowedFunctions: ['include']);
385+
$sandbox = new SandboxExtension($policy, false);
386+
$twig->addExtension($sandbox);
387+
388+
// The template is loaded without the sandbox enabled
389+
// so, no compile error
390+
$twig->load('included');
391+
392+
// We expect a runtime error
393+
$this->expectException(SecurityError::class);
394+
$twig->render('index');
395+
}
357396
}
358397

359398
final class CoreTestIteratorAggregate implements \IteratorAggregate

0 commit comments

Comments
 (0)
Please sign in to comment.