VYPR
High severityNVD Advisory· Published Mar 21, 2024· Updated Aug 21, 2024

Grav vulnerable to Server Side Template Injection (SSTI) via Twig escape handler

CVE-2024-28119

Description

Grav is an open-source, flat-file content management system. Prior to version 1.7.45, due to the unrestricted access to twig extension class from grav context, an attacker can redefine the escape function and execute arbitrary commands. Twig processing of static pages can be enabled in the front matter by any administrative user allowed to create or edit pages. As the Twig processor runs unsandboxed, this behavior can be used to gain arbitrary code execution and elevate privileges on the instance. Version 1.7.45 contains a patch for this issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
getgrav/gravPackagist
< 1.7.451.7.45

Affected products

1

Patches

1
de1ccfa12dbc

Mitigate various SSTI injections

https://github.com/getgrav/gravAndy MillerMar 4, 2024via ghsa
3 files changed · +30 3
  • CHANGELOG.md+2 1 modified
    @@ -6,7 +6,8 @@
     1. [](#bugfix)
        * Fixed some multibyte issues in Inflector class [#732](https://github.com/getgrav/grav/issues/732)
        * Fallback to page modified date if Page date provided is invalid and can't be parsed [getgrav/grav-plugin-admin#2394](https://github.com/getgrav/grav-plugin-admin/issues/2394)
    -   * Fixed a path traversal vulnerability with file uploads [GHSA-m7hx-hw6h-mqmc](https://github.com/getgrav/grav/security/advisories/GHSA-m7hx-hw6h-mqmc)
    +   * Fixed a path traversal vulnerability with file uploads [#GHSA-m7hx-hw6h-mqmc](https://github.com/getgrav/grav/security/advisories/GHSA-m7hx-hw6h-mqmc)
    +   * Fixed a security issue with insecure Twig functions be processed [#GHSA-2m7x-c7px-hp58](https://github.com/getgrav/grav/security/advisories/GHSA-2m7x-c7px-hp58) [#GHSA-r6vw-8v8r-pmp4](https://github.com/getgrav/grav/security/advisories/GHSA-r6vw-8v8r-pmp4) [#GHSA-qfv4-q44r-g7rv](https://github.com/getgrav/grav/security/advisories/GHSA-qfv4-q44r-g7rv)
     
     # v1.7.44
     ## 01/05/2024
    
  • system/src/Grav/Common/Security.php+19 0 modified
    @@ -263,4 +263,23 @@ public static function getXssDefaults(): array
                 'invalid_protocols' => array_map('trim', $config->get('security.xss_invalid_protocols')),
             ];
         }
    +
    +    public static function cleanDangerousTwig(string $string): string
    +    {
    +        if ($string === '') {
    +            return $string;
    +        }
    +
    +        $bad_twig = [
    +            'twig_array_map',
    +            'twig_array_filter',
    +            'call_user_func',
    +            'registerUndefinedFunctionCallback',
    +            'undefined_functions',
    +            'twig.getFunction',
    +            'core.setEscaper',
    +        ];
    +        $string = preg_replace('/(({{\s*|{%\s*)[^}]*?(' . implode('|', $bad_twig) . ')[^}]*?(\s*}}|\s*%}))/i', '{# $1 #}', $string);
    +        return $string;
    +    }
     }
    
  • system/src/Grav/Common/Twig/Twig.php+9 2 modified
    @@ -16,6 +16,7 @@
     use Grav\Common\Language\LanguageCodes;
     use Grav\Common\Page\Interfaces\PageInterface;
     use Grav\Common\Page\Pages;
    +use Grav\Common\Security;
     use Grav\Common\Twig\Exception\TwigException;
     use Grav\Common\Twig\Extension\FilesystemExtension;
     use Grav\Common\Twig\Extension\GravExtension;
    @@ -319,6 +320,7 @@ public function setTemplate($name, $template)
         public function processPage(PageInterface $item, $content = null)
         {
             $content = $content ?? $item->content();
    +        $content = Security::cleanDangerousTwig($content);
     
             // override the twig header vars for local resolution
             $this->grav->fireEvent('onTwigPageVariables', new Event(['page' => $item]));
    @@ -392,6 +394,8 @@ public function processString($string, array $vars = [])
             $this->grav->fireEvent('onTwigStringVariables');
             $vars += $this->twig_vars;
     
    +        $string = Security::cleanDangerousTwig($string);
    +
             $name = '@Var:' . $string;
             $this->setTemplate($name, $string);
     
    @@ -418,7 +422,7 @@ public function processSite($format = null, array $vars = [])
             try {
                 $grav = $this->grav;
     
    -            // set the page now its been processed
    +            // set the page now it's been processed
                 $grav->fireEvent('onTwigSiteVariables');
     
                 /** @var Pages $pages */
    @@ -427,13 +431,15 @@ public function processSite($format = null, array $vars = [])
                 /** @var PageInterface $page */
                 $page = $grav['page'];
     
    +            $content = Security::cleanDangerousTwig($page->content());
    +
                 $twig_vars = $this->twig_vars;
                 $twig_vars['theme'] = $grav['config']->get('theme');
                 $twig_vars['pages'] = $pages->root();
                 $twig_vars['page'] = $page;
                 $twig_vars['header'] = $page->header();
                 $twig_vars['media'] = $page->media();
    -            $twig_vars['content'] = $page->content();
    +            $twig_vars['content'] = $content;
     
                 // determine if params are set, if so disable twig cache
                 $params = $grav['uri']->params(null, true);
    @@ -568,4 +574,5 @@ public function setAutoescape($state)
     
             $this->autoescape = (bool) $state;
         }
    +
     }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.