| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- <?php
- declare(strict_types=1);
- namespace App\Tests\Integration\App;
- use App\Tests\Integration\Support\AppTestCase;
- use Slim\Views\Twig;
- use Twig\Extension\EscaperExtension;
- /**
- * SEC_REVIEW F63 — pin Twig's autoescape strategy to `'html'`. The
- * current Twig major defaults to `'html'`, but the SEC_REVIEW asked
- * us not to rely on the default in case a future major bump or a
- * Slim-twig wrapper change silently flips it.
- */
- final class TwigConfigTest extends AppTestCase
- {
- protected function setUp(): void
- {
- $this->bootApp();
- }
- public function testAutoescapeStrategyIsExplicitlyHtml(): void
- {
- /** @var Twig $twig */
- $twig = $this->container->get(Twig::class);
- $escaper = $twig->getEnvironment()->getExtension(EscaperExtension::class);
- // `getDefaultStrategy` takes the template name; for the
- // pinned `'html'` policy it returns the strategy regardless
- // of name.
- self::assertSame('html', $escaper->getDefaultStrategy('any.twig'));
- self::assertSame('html', $escaper->getDefaultStrategy('pages/login.twig'));
- }
- public function testRenderedTemplateAutoescapesUserInput(): void
- {
- // Defence-in-depth: render a string with a script tag through
- // `{{ value }}` and confirm the output is HTML-escaped. The
- // unit test above pins the configured strategy; this one
- // proves the pipeline actually applies it.
- /** @var Twig $twig */
- $twig = $this->container->get(Twig::class);
- $env = $twig->getEnvironment();
- $env->setLoader(new \Twig\Loader\ArrayLoader([
- 'inline.twig' => 'value=[{{ value }}]',
- ]));
- $rendered = $env->render('inline.twig', ['value' => '<script>alert(1)</script>']);
- self::assertSame(
- 'value=[<script>alert(1)</script>]',
- $rendered,
- );
- }
- }
|