CVE-2026-72698
Grav CMS before 2.0.16 Information Disclosure via Twig Sandbox Bypass
Grav CMS before 2.0.16 fails to filter system, site, and theme configuration arrays in sandboxed Twig renders, allowing content editors to read sensitive configuration values. Attackers with page-content edit access can access raw configuration arrays including secrets like cache credentials by using dot notation in Twig templates, bypassing the config_denied_paths restrictions.
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
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
7.1
Grav CMS before 2.0.16 Information Disclosure via Twig Sandbox Bypass
Grav CMS before 2.0.16 fails to filter system, site, and theme configuration arrays in sandboxed Twig renders, allowing content editors to read sensitive configuration values. Attackers with page-content edit access can access raw configuration arrays including secrets like cache credentials by using dot notation in Twig templates, bypassing the config_denied_paths restrictions.
- Record
CVE-2026-72698- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
EUVDEUVD-2026-65212
7.1
Grav CMS before 2.0.16 fails to filter system, site, and theme configuration arrays in sandboxed Twig renders, allowing content editors to read sensitive configuration values. Attackers with page-content edit access can access raw configuration arrays including secrets like cache credentials by using dot notation in Twig templates, bypassing the config_denied_paths restrictions.
- Record
EUVD-2026-65212- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-mw85-cjh9-8hp7
7.1
Duplicate Advisory: Grav: The system, site, and theme Twig variables bypass the content sandbox entirely and are never covered by config_denied_paths
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-p597-crqc-m349. This link is maintained to preserve external references.
Original Description
Grav CMS before 2.0.16 fails to filter system, site, and theme configuration arrays in sandboxed Twig renders, allowing content editors to read sensitive configuration values. Attackers with page-content edit access can access raw configuration arrays including secrets like cache credentials by using dot notation in Twig templates, bypassing the config_denied_paths restrictions.
- Record
GHSA-mw85-cjh9-8hp7- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-p597-crqc-m349
7.1
Grav: The system, site, and theme Twig variables bypass the content sandbox entirely and are never covered by config_denied_paths
Summary
Grav\Common\Twig\Twig::init() unconditionally puts the raw system, site, and theme config arrays into $this->twig_vars. Twig::processPage() builds the variables for the sandboxed, editor-authored page-content render by copying that same base array ($sandbox_vars = $twig_vars;) and replacing only the config key with a filtered SandboxConfig facade. The system, site, and theme keys are carried into the sandboxed render completely untouched.
Because these are plain PHP arrays, not objects, Twig's sandbox SecurityPolicy (the allowed_classes/allowed_methods/allowed_properties lists in system/config/security.yaml) has no jurisdiction over them at all. The sandbox only gates method calls and property access on objects. Dot notation or subscript access on an array is always allowed by Twig regardless of any sandbox policy. So {{ system.cache.redis.password }} in page content renders the value directly, with the sandbox doing nothing to stop it, and with security.twig_sandbox.config_denied_paths never even being consulted, since that list only filters the separate config facade object, not the system array.
This means: even on a default install where twig_content.config_access is false (its documented default) so the config Twig variable is empty inside sandboxed renders, an attacker with page-content edit access (or a stored-XSS-style Twig injection into page content, if twig_content.process_enabled is on) can still read system.*, site.*, and theme.* in full, including any admin-configured secret nested under those trees.
Affected product and version
Product: Grav CMS, getgrav/grav Confirmed present in: 2.0.15, commit c2b46866857a93a0aa7048e7ed707ed3ed45dbc3
Affected code
system/src/Grav/Common/Twig/Twig.php, in init(), the base variable set (around line 300):
$this->twig_vars += [
'config' => $config,
'system' => $config->get('system'),
'theme' => $config->get('theme'),
'site' => $config->get('site'),
'uri' => $this->grav['uri'],
...
];
system/src/Grav/Common/Twig/Twig.php, in processPage(), where the sandboxed render variables are built (around line 419-429):
if ($item->shouldProcess('twig') || $item->isModule()) {
$name = '@Page:' . $item->path();
$this->setTemplate($name, $content);
// Replace `config` with a denied-path-filtered facade for the
// sandboxed render so editors can't exfiltrate plugin secrets
// via `config.toArray()` (GHSA-j274-39qw-32c9). The modular
// theme render below is unsandboxed and keeps the raw Config.
$sandbox_vars = $twig_vars;
$sandbox_vars['config'] = $this->buildSandboxConfig();
try {
$output = $content = $local_twig->render($name, $sandbox_vars);
...
Only $sandbox_vars['config'] is replaced. $sandbox_vars['system'], $sandbox_vars['site'], and $sandbox_vars['theme'] still point at the exact same raw arrays that were assigned in init().
system/config/system.yaml shows a concrete real secret field that lives under system:
cache:
redis:
socket: false
password: # Optional password
database:
Root cause
Two separate things have to both be true for this to be reachable, and they both are:
- The sandbox's
SecurityPolicyonly checks object method calls and object property access (checkMethodAllowed,checkPropertyAllowedin Twig'sSandbox\SecurityPolicy). It has no concept of restricting array key access, because Twig's own design does not treat plain array reads as something a sandbox policy needs to arbitrate.config_denied_pathsis implemented entirely insideSandboxConfig, a wrapper object with its ownget()/offsetGet()that consults the denied list, that facade is what makesconfigsafe.system/site/themenever get wrapped in…
- Record
GHSA-p597-crqc-m349- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
NVD
7.1
Grav CMS before 2.0.16 fails to filter system, site, and theme configuration arrays in sandboxed Twig renders, allowing content editors to read sensitive configuration values. Attackers with page-content edit access can access raw configuration arrays including secrets like cache credentials by using dot notation in Twig templates, bypassing the config_denied_paths restrictions.
- Record
CVE-2026-72698- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSV
7.1
Grav CMS before 2.0.16 Information Disclosure via Twig Sandbox Bypass
Grav CMS before 2.0.16 fails to filter system, site, and theme configuration arrays in sandboxed Twig renders, allowing content editors to read sensitive configuration values. Attackers with page-content edit access can access raw configuration arrays including secrets like cache credentials by using dot notation in Twig templates, bypassing the config_denied_paths restrictions.
- Record
CVE-2026-72698- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSVGHSA-mw85-cjh9-8hp7
7.1
Duplicate Advisory: Grav: The system, site, and theme Twig variables bypass the content sandbox entirely and are never covered by config_denied_paths
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-p597-crqc-m349. This link is maintained to preserve external references.
Original Description
Grav CMS before 2.0.16 fails to filter system, site, and theme configuration arrays in sandboxed Twig renders, allowing content editors to read sensitive configuration values. Attackers with page-content edit access can access raw configuration arrays including secrets like cache credentials by using dot notation in Twig templates, bypassing the config_denied_paths restrictions.
- Record
GHSA-mw85-cjh9-8hp7- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
OSVGHSA-p597-crqc-m349
7.1
Grav: The system, site, and theme Twig variables bypass the content sandbox entirely and are never covered by config_denied_paths
Summary
Grav\Common\Twig\Twig::init() unconditionally puts the raw system, site, and theme config arrays into $this->twig_vars. Twig::processPage() builds the variables for the sandboxed, editor-authored page-content render by copying that same base array ($sandbox_vars = $twig_vars;) and replacing only the config key with a filtered SandboxConfig facade. The system, site, and theme keys are carried into the sandboxed render completely untouched.
Because these are plain PHP arrays, not objects, Twig's sandbox SecurityPolicy (the allowed_classes/allowed_methods/allowed_properties lists in system/config/security.yaml) has no jurisdiction over them at all. The sandbox only gates method calls and property access on objects. Dot notation or subscript access on an array is always allowed by Twig regardless of any sandbox policy. So {{ system.cache.redis.password }} in page content renders the value directly, with the sandbox doing nothing to stop it, and with security.twig_sandbox.config_denied_paths never even being consulted, since that list only filters the separate config facade object, not the system array.
This means: even on a default install where twig_content.config_access is false (its documented default) so the config Twig variable is empty inside sandboxed renders, an attacker with page-content edit access (or a stored-XSS-style Twig injection into page content, if twig_content.process_enabled is on) can still read system.*, site.*, and theme.* in full, including any admin-configured secret nested under those trees.
Affected product and version
Product: Grav CMS, getgrav/grav Confirmed present in: 2.0.15, commit c2b46866857a93a0aa7048e7ed707ed3ed45dbc3
Affected code
system/src/Grav/Common/Twig/Twig.php, in init(), the base variable set (around line 300):
$this->twig_vars += [
'config' => $config,
'system' => $config->get('system'),
'theme' => $config->get('theme'),
'site' => $config->get('site'),
'uri' => $this->grav['uri'],
...
];
system/src/Grav/Common/Twig/Twig.php, in processPage(), where the sandboxed render variables are built (around line 419-429):
if ($item->shouldProcess('twig') || $item->isModule()) {
$name = '@Page:' . $item->path();
$this->setTemplate($name, $content);
// Replace `config` with a denied-path-filtered facade for the
// sandboxed render so editors can't exfiltrate plugin secrets
// via `config.toArray()` (GHSA-j274-39qw-32c9). The modular
// theme render below is unsandboxed and keeps the raw Config.
$sandbox_vars = $twig_vars;
$sandbox_vars['config'] = $this->buildSandboxConfig();
try {
$output = $content = $local_twig->render($name, $sandbox_vars);
...
Only $sandbox_vars['config'] is replaced. $sandbox_vars['system'], $sandbox_vars['site'], and $sandbox_vars['theme'] still point at the exact same raw arrays that were assigned in init().
system/config/system.yaml shows a concrete real secret field that lives under system:
cache:
redis:
socket: false
password: # Optional password
database:
Root cause
Two separate things have to both be true for this to be reachable, and they both are:
- The sandbox's
SecurityPolicyonly checks object method calls and object property access (checkMethodAllowed,checkPropertyAllowedin Twig'sSandbox\SecurityPolicy). It has no concept of restricting array key access, because Twig's own design does not treat plain array reads as something a sandbox policy needs to arbitrate.config_denied_pathsis implemented entirely insideSandboxConfig, a wrapper object with its ownget()/offsetGet()that consults the denied list, that facade is what makesconfigsafe.system/site/themenever get wrapped in…
- Record
GHSA-p597-crqc-m349- CVSS 4.0
- 7.1 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-200
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
getgrav/gravPackagist |
before 2.0.16 | 2.0.16 |
getgrav/gravPackagist |
before 2.0.16, plus listed versions 0.8.00.9.00.9.10.9.100.9.11 Show 45 moreShow less0.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 |
2.0.16 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-72698 is a high vulnerability (CVSS 7.1) in Getgrav Grav, published August 25, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.41%, the 35th percentile. Fixed in getgrav/grav 2.0.16.
References
github.com/getgrav/grav/security/advisories/GHSA-p597-crqc-m349
vulncheck.com/advisories/grav-cms-before-information-disclosure-via-twig-sandbox-bypass
nvd.nist.gov/vuln/detail/CVE-2026-72698
github.com/advisories/GHSA-mw85-cjh9-8hp7
github.com/advisories/GHSA-p597-crqc-m349
github.com/CVEProject/cvelistV5/tree/main/cves/2026/72xxx/CVE-2026-72698.json
github.com/getgrav/grav
Left out here: 300 versions and the rest of 2 source descriptions. The JSON record has them.