Skip to content

Commit

Permalink
Fix a security issue when an included sandboxed template has been loa…
Browse files Browse the repository at this point in the history
…ded before without the sandbox context
  • Loading branch information
fabpot committed Sep 9, 2024
1 parent a1d84cf commit 2102dd1
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
11 changes: 4 additions & 7 deletions src/Extension/CoreExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -1268,13 +1268,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();
}
}
}

try {
Expand All @@ -1287,6 +1280,10 @@ function twig_include(Environment $env, $context, $template, $variables = [], $w
}
}

if ($isSandboxed && $loaded) {
$loaded->unwrap()->checkSecurity();
}

return $loaded ? $loaded->render($variables) : '';
} finally {
if ($isSandboxed && !$alreadySandboxed) {
Expand Down
38 changes: 38 additions & 0 deletions tests/Extension/CoreTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
use PHPUnit\Framework\TestCase;
use Twig\Environment;
use Twig\Error\RuntimeError;
use Twig\Extension\SandboxExtension;
use Twig\Loader\ArrayLoader;
use Twig\Loader\LoaderInterface;
use Twig\Sandbox\SecurityError;
use Twig\Sandbox\SecurityPolicy;

class CoreTest extends TestCase
{
Expand Down Expand Up @@ -251,6 +255,40 @@ public function provideSliceFilterCases()
[[], 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');
}
}

final class CoreTestIteratorAggregate implements \IteratorAggregate
Expand Down

0 comments on commit 2102dd1

Please sign in to comment.