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 0887422 commit 7afa198
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 @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
38 changes: 38 additions & 0 deletions tests/Extension/CoreTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
*/

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
{
Expand Down Expand Up @@ -283,6 +287,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');
}
}

function foo_escaper_for_test(Environment $env, $string, $charset)
Expand Down

0 comments on commit 7afa198

Please sign in to comment.