From e3549f722a0a2e1b2c8a7b516997d95892839df2 Mon Sep 17 00:00:00 2001 From: Tim Date: Sun, 11 May 2025 00:37:50 +0200 Subject: [PATCH] Secure the twig renderer template loader --- src/Service/SnipParser/Twig/SnipLoader.php | 6 ++++++ src/Service/SnipParser/Twig/SnipTwigExtension.php | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Service/SnipParser/Twig/SnipLoader.php b/src/Service/SnipParser/Twig/SnipLoader.php index 50b0806..845be3e 100644 --- a/src/Service/SnipParser/Twig/SnipLoader.php +++ b/src/Service/SnipParser/Twig/SnipLoader.php @@ -4,7 +4,9 @@ namespace App\Service\SnipParser\Twig; use App\Entity\Snip; use App\Repository\SnipRepository; +use App\Security\Voter\SnipVoter; use App\Service\SnipContent\SnipContentService; +use Symfony\Bundle\SecurityBundle\Security; use Twig\Error\LoaderError; use Twig\Loader\LoaderInterface; use Twig\Source; @@ -14,6 +16,7 @@ class SnipLoader implements LoaderInterface public function __construct( private readonly SnipRepository $repository, private readonly SnipContentService $contentService, + private readonly Security $security, ) {} public function getSourceContext(string $name): Source @@ -50,6 +53,9 @@ class SnipLoader implements LoaderInterface if (!$snip) { throw new LoaderError(\sprintf('Template "%s" is not defined.', $key)); } + if (!$this->security->isGranted(SnipVoter::VIEW, $snip)) { + throw new LoaderError(\sprintf('You do not have permission to view the template "%s".', $key)); + } return $snip; } diff --git a/src/Service/SnipParser/Twig/SnipTwigExtension.php b/src/Service/SnipParser/Twig/SnipTwigExtension.php index de249b1..e570074 100644 --- a/src/Service/SnipParser/Twig/SnipTwigExtension.php +++ b/src/Service/SnipParser/Twig/SnipTwigExtension.php @@ -48,8 +48,13 @@ class SnipTwigExtension extends AbstractExtension private function snipsByTag(string $tag): array { + // Todo: get 'context' user from the snip it is called from + $user = $this->security->getUser(); + if ($user === null) { + return []; + } $request = new SnipFilterRequest(SnipFilterRequest::VISIBILITY_ALL, tag: $tag); - $snips = $this->snipRepo->findByRequest($this->security->getUser(), $request); + $snips = $this->snipRepo->findByRequest($user, $request); return array_map(fn(Snip $snip) => [ 'id' => $snip->getId(), 'name' => $snip->getName(),