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 10, 2024
1 parent e80fb8e commit 41103dc
Show file tree
Hide file tree
Showing 2 changed files with 43 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 @@ -1400,13 +1400,6 @@ public static function include(Environment $env, $context, $template, $variables
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 @@ -1419,6 +1412,10 @@ public static function include(Environment $env, $context, $template, $variables
}
}

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

return $loaded ? $loaded->render($variables) : '';
} finally {
if ($isSandboxed && !$alreadySandboxed) {
Expand Down
39 changes: 39 additions & 0 deletions tests/Extension/CoreTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@
*/

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
{
Expand Down Expand Up @@ -313,6 +318,40 @@ public function provideCompareCases()
[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
Expand Down

0 comments on commit 41103dc

Please sign in to comment.