Every CVE Search/ Get API key

CVE-2025-66294

Grav is vulnerable to RCE via SSTI through Twig Sandbox Bypass

8.7 HighPublic exploitFix available

Grav is a file-based Web platform. Prior to 1.8.0-beta.27, a Server-Side Template Injection (SSTI) vulnerability exists in Grav that allows authenticated attackers with editor permissions to execute arbitrary commands on the server and, under certain conditions, may also be exploited by unauthenticated attackers. This vulnerability stems from weak regex validation in the cleanDangerousTwig method. This vulnerability is fixed in 1.8.0-beta.27.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

3.02%Up 3.0 points since Dec 2, 2025
90%50%10%1%

What each source reports

CVE List Score used 8.7

Grav is vulnerable to RCE via SSTI through Twig Sandbox Bypass

Grav is a file-based Web platform. Prior to 1.8.0-beta.27, a Server-Side Template Injection (SSTI) vulnerability exists in Grav that allows authenticated attackers with editor permissions to execute arbitrary commands on the server and, under certain conditions, may also be exploited by unauthenticated attackers. This vulnerability stems from weak regex validation in the cleanDangerousTwig method. This vulnerability is fixed in 1.8.0-beta.27.

Record
CVE-2025-66294
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-94, CWE-1336
Updated
2026-11-02
EUVDEUVD-2025-200081 8.7

Grav is a file-based Web platform. Prior to 1.8.0-beta.27, a Server-Side Template Injection (SSTI) vulnerability exists in Grav that allows authenticated attackers with editor permissions to execute arbitrary commands on the server and, under certain conditions, may also be exploited by unauthenticated attackers. This vulnerability stems from weak regex validation in the cleanDangerousTwig method. This vulnerability is fixed in 1.8.0-beta.27.

Record
EUVD-2025-200081
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-662m-56v4-3r8f 8.7

Grav is vulnerable to RCE via SSTI through Twig Sandbox Bypass

Summary

A Server-Side Template Injection (SSTI) vulnerability exists in Grav that allows authenticated attackers with editor permissions to execute arbitrary commands on the server and, under certain conditions, may also be exploited by unauthenticated attackers. This vulnerability stems from weak regex validation in the cleanDangerousTwig method.

Important

  • First of all this vulnerability is due to weak sanitization in the method clearDangerousTwig, so any other class that calls it indirectly through for example $twig->processString to sanitize code is also vulnerable.

  • For this report, we will need the official Form and Admin plugin installed, also I will be chaining this with another vulnerability to allow an editor which is a user with only pages permissions to edit the process section of a form.

  • I made another report for the other vulnerability which is a Broken Access Control which allows a user with full permission for pages to change the process section by intercepting the request and modifying it.

Permissions Needed

  • The main case for this vulnerability is an editor which can unconditionally takeover the whole system through creating a vulnerable form.
  • Second case is as an unauthenticated user, so if the form exists already and accepts user input and puts it through evaluate_twig, a guest can takeover the system.

Details

When we make a form with a process section and a message action, when the form is submitted we get to deal with onFormProcess in form.php through the message case:

            case 'message':
                $translated_string = $this->grav['language']->translate($params);
                $vars = array(
                    'form' => $form
                );

                /** @var Twig $twig */
                $twig = $this->grav['twig'];
                $processed_string = $twig->processString($translated_string, $vars);

                $form->message = $processed_string;
                break;

Which takes our parameters as in our action values, like in our case the value of our message action and sends it to processString which then calls the method cleanDangerousTwig from Security.php, now here's where we find the vulnerability is caused by two things:

  • First of all is weak regex which doesn't account for nested function calls, which allows us to bypass this function's sanitization
  • Second issue which is the evaluate and evaluate_twig functions which are allowed, and since we can call Twig syntax from inside them, it will lead to nested function calls which we can bypass and thus execute arbitrary payloads.
    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',
            'twig.safe_functions',
            'read_file',
        ];
         
        // This allows for a payload like {{ evaluate("read_file('/etc/passwd')") }}
        $string = preg_replace('/(({{\s*|{%\s*)[^}]*?(' . implode('|', $bad_twig) . ')[^}]*?(\s*}}|\s*%}))/i', '{# $1 #}', $string);
        return $string;
    }

PoC

First to showcase how the function handles the payload, I built a small php program that replicates the behavior of cleanDangerousTwig:

<?php

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',
        'twig.safe_functions',
        'read_file',
    ];
    $string =…
Record
GHSA-662m-56v4-3r8f
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-94, CWE-1336
Updated
2026-11-02
NVD 8.7

Grav is a file-based Web platform. Prior to 1.8.0-beta.27, a Server-Side Template Injection (SSTI) vulnerability exists in Grav that allows authenticated attackers with editor permissions to execute arbitrary commands on the server and, under certain conditions, may also be exploited by unauthenticated attackers. This vulnerability stems from weak regex validation in the cleanDangerousTwig method. This vulnerability is fixed in 1.8.0-beta.27.

Record
CVE-2025-66294
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
CVSS 3.1
8.8 HighCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-94, CWE-1336
Updated
2026-11-02
OSV 8.7

Grav is vulnerable to RCE via SSTI through Twig Sandbox Bypass

Grav is a file-based Web platform. Prior to 1.8.0-beta.27, a Server-Side Template Injection (SSTI) vulnerability exists in Grav that allows authenticated attackers with editor permissions to execute arbitrary commands on the server and, under certain conditions, may also be exploited by unauthenticated attackers. This vulnerability stems from weak regex validation in the cleanDangerousTwig method. This vulnerability is fixed in 1.8.0-beta.27.

Record
CVE-2025-66294
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-1336, CWE-94
Updated
2026-11-02
OSVGHSA-662m-56v4-3r8f 8.7

Grav is vulnerable to RCE via SSTI through Twig Sandbox Bypass

Summary

A Server-Side Template Injection (SSTI) vulnerability exists in Grav that allows authenticated attackers with editor permissions to execute arbitrary commands on the server and, under certain conditions, may also be exploited by unauthenticated attackers. This vulnerability stems from weak regex validation in the cleanDangerousTwig method.

Important

  • First of all this vulnerability is due to weak sanitization in the method clearDangerousTwig, so any other class that calls it indirectly through for example $twig->processString to sanitize code is also vulnerable.

  • For this report, we will need the official Form and Admin plugin installed, also I will be chaining this with another vulnerability to allow an editor which is a user with only pages permissions to edit the process section of a form.

  • I made another report for the other vulnerability which is a Broken Access Control which allows a user with full permission for pages to change the process section by intercepting the request and modifying it.

Permissions Needed

  • The main case for this vulnerability is an editor which can unconditionally takeover the whole system through creating a vulnerable form.
  • Second case is as an unauthenticated user, so if the form exists already and accepts user input and puts it through evaluate_twig, a guest can takeover the system.

Details

When we make a form with a process section and a message action, when the form is submitted we get to deal with onFormProcess in form.php through the message case:

            case 'message':
                $translated_string = $this->grav['language']->translate($params);
                $vars = array(
                    'form' => $form
                );

                /** @var Twig $twig */
                $twig = $this->grav['twig'];
                $processed_string = $twig->processString($translated_string, $vars);

                $form->message = $processed_string;
                break;

Which takes our parameters as in our action values, like in our case the value of our message action and sends it to processString which then calls the method cleanDangerousTwig from Security.php, now here's where we find the vulnerability is caused by two things:

  • First of all is weak regex which doesn't account for nested function calls, which allows us to bypass this function's sanitization
  • Second issue which is the evaluate and evaluate_twig functions which are allowed, and since we can call Twig syntax from inside them, it will lead to nested function calls which we can bypass and thus execute arbitrary payloads.
    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',
            'twig.safe_functions',
            'read_file',
        ];
         
        // This allows for a payload like {{ evaluate("read_file('/etc/passwd')") }}
        $string = preg_replace('/(({{\s*|{%\s*)[^}]*?(' . implode('|', $bad_twig) . ')[^}]*?(\s*}}|\s*%}))/i', '{# $1 #}', $string);
        return $string;
    }

PoC

First to showcase how the function handles the payload, I built a small php program that replicates the behavior of cleanDangerousTwig:

<?php

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',
        'twig.safe_functions',
        'read_file',
    ];
    $string =…
Record
GHSA-662m-56v4-3r8f
CVSS 4.0
8.7 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-1336, CWE-94
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
getgrav/grav
Packagist
before 1.8.0-beta.27
1.8.0-beta.27
getgrav/grav
Packagist
before 1.8.0-beta.27, plus listed versions
0.8.00.9.00.9.10.9.100.9.11
Show 45 moreShow less
0.9.120.9.130.9.140.9.150.9.160.9.170.9.180.9.190.9.20.9.200.9.210.9.220.9.230.9.240.9.250.9.260.9.270.9.280.9.290.9.30.9.300.9.310.9.320.9.330.9.340.9.350.9.360.9.370.9.380.9.390.9.40.9.400.9.410.9.420.9.430.9.440.9.450.9.50.9.60.9.70.9.80.9.91.0.01.0.0-rc.11.0.0-rc.2
1.8.0-beta.27

Public exploits

Links only. Every CVE stores no exploit code.

Public exploits
SourceLinkDate
MetasploitGrav CMS Twig SSTI Authenticated Sandbox Bypass RCE2025-12-01

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, Metasploit, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2025-66294 is a high vulnerability (CVSS 8.7) in Getgrav Grav, published December 1, 2025. Public exploit code exists. EPSS puts the chance of exploitation in the next 30 days at 3.02%, the 87th percentile. Fixed in getgrav/grav 1.8.0-beta.27.

References

This page doesn't list everything

Left out here: 267 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open