Fix sandbox bypass: PHP code injection via {% use %} template name

This commit is contained in:
Alexandre Daubois
2026-04-28 13:25:53 +02:00
committed by Fabien Potencier
parent afe54db2e5
commit e9ff55f691
2 changed files with 27 additions and 3 deletions
+24
View File
@@ -21,6 +21,7 @@ namespace Twig\Tests\Node;
*/
use Twig\Environment;
use Twig\Error\RuntimeError;
use Twig\Loader\ArrayLoader;
use Twig\Node\BodyNode;
use Twig\Node\EmptyNode;
@@ -56,6 +57,29 @@ class ModuleTest extends NodeTestCase
$this->assertEquals($source->getName(), $node->getTemplateName());
}
public function testUseTagTemplateNameDoesNotInjectPhpInCompiledOutput()
{
$evilName = "evil' . print('BAD-EOL') . '.twig";
$loader = new ArrayLoader([
$evilName => '{% block existing %}ok{% endblock %}',
'main.twig' => "{% use \"$evilName\" with absent_block as alias %}",
]);
$twig = new Environment($loader);
ob_start();
$message = null;
try {
$twig->load('main.twig');
} catch (RuntimeError $e) {
$message = $e->getMessage();
}
$stdout = ob_get_clean();
$this->assertSame('', $stdout, 'No code from the template name must execute when the trait is loaded.');
$this->assertNotNull($message, 'A RuntimeError must be raised for the missing block.');
$this->assertStringContainsString($evilName, $message, 'The error message must contain the literal template name.');
}
public static function provideTests(): iterable
{
$twig = new Environment(new ArrayLoader(['foo.twig' => '{{ foo }}']));