Summary
Grav CMS blueprints allow dynamic field directives to invoke fully-qualified static PHP methods without adequate validation, bypassing the existing dangerous-callable denylist.
An attacker with page-editing rights can craft frontmatter that calls arbitrary public static methods with controlled arguments, enabling file disclosure and server-side file manipulation when the page is rendered.
Affected context
The vulnerability appears in Grav CMS installations using blueprint dynamic-field directives within page frontmatter forms.
It becomes relevant when non-super-admin users with admin.pages permissions can create or modify pages that include dynamic field definitions.
The risk is most pronounced in environments where page frontmatter is interpreted server-side to resolve dynamic field values using PHP method calls, and where public static methods can be used as gadgets to access or modify the filesystem.
Exploit preconditions
- Attack surface: Grav CMS page editing interface and frontmatter-based form field definitions.
- Required access: An authenticated CMS account with
admin.pagespermission (but not necessarily super-admin oradmin.pages_twig). - Trigger point: Rendering or processing of a page whose blueprint contains a dynamic-field directive with a crafted
Class::methodreference. - Why exploitation is possible: The
Blueprint::isSafeDynamicCall()routine only applies its denylist to unqualified method names (without::), allowing any fully-qualified static method call string to bypass safety checks and execute with attacker-controlled arguments.
Why this happens
The core issue is a validation gap in the blueprint dynamic-call safety filter.
The safety check assumes risk is limited to simple, unqualified callable names and applies a denylist only when no :: is present in the call string.
As a result, fully-qualified static method references such as Some\Class::dangerousMethod are treated as inherently safe, even though they can be resolved and invoked at runtime with attacker-provided parameters.
This maps to CWE-94: Code Injection, where application logic permits user-controlled identifiers or call targets to influence server-side code execution without robust constraint or vetting.
Potential impact
- Attackers may read any file that the web server account can access, exposing configuration data and secrets.
- Crafted pages could disclose sensitive file contents to anonymous visitors who load the page.
- Attackers can create, copy, or overwrite files and directories under the web server account's permissions, potentially altering site content or planting malicious resources.
- Application integrity can be degraded through unauthorized file operations and configuration changes.
- In some deployments, file-level manipulation could assist in further compromise or lateral movement within the hosting environment.
General mitigation guidance
Effective mitigation focuses on constraining dynamic callable resolution and limiting what frontmatter can direct the runtime to execute.
Recommended patterns include:
- Treating all user-influenced references to code entities (classes, methods, functions) as untrusted and enforcing strict whitelists for permissible call targets.
- Normalizing dynamic-call strings before validation so that safety rules apply uniformly to both qualified and unqualified call forms.
- Restricting blueprint dynamic-field directives to a fixed set of non-sensitive helpers that do not perform file I/O or other side-effect-heavy operations.
- Segregating privileges so that roles allowed to edit pages cannot indirectly trigger administrative or filesystem-affecting behaviors.
- Applying least-privilege to the web server account, reducing the set of files and directories that can be read or written even if a gadget is invoked.
How teams detect issues like this
Detection often involves a mix of static inspection and runtime monitoring:
- Reviewing blueprint and frontmatter processing code for dynamic callable resolution patterns, especially where strings are mapped to
Class::methodpairs. - Employing static analysis rules that flag user-controlled data flowing into reflection, dynamic invocation, or callable resolution functions.
- Implementing configuration or policy checks that enforce whitelists on callable targets used by dynamic field engines.
- Auditing CMS content repositories for suspicious blueprint directives, such as unexpected fully-qualified static method calls in page frontmatter.
- Using automated code review tools to highlight locations where validation is applied conditionally based on string structure, which can open bypass opportunities.

