Summary
An improper path validation issue in the Grav API Plugin allows crafted slugs in the POST /pages/{route}/move endpoint to be interpreted as filesystem paths containing traversal sequences.
When an authenticated caller with page write permissions abuses this behavior, they can relocate page directories and media to arbitrary writable locations, potentially outside the Grav installation.
An improper path validation issue in the Grav API Plugin allows crafted slugs in the POST /pages/{route}/move endpoint to be interpreted as filesystem paths containing traversal sequences.
When an authenticated caller with page write permissions abuses this behavior, they can relocate page directories and media to arbitrary writable locations, potentially outside the Grav installation.
Affected context
This vulnerability appears in Grav-based sites that use the API plugin to manage pages through POST /pages/{route}/move.
It is relevant where:
- The
getgrav/grav-plugin-apipackage is deployed below version 1.0.10 - API access with
api.pages.writepermission is granted to users or automation - The underlying filesystem allows the web process to write outside
user/pages/
In such environments, user-supplied slugs are treated as directory paths with insufficient normalization, enabling traversal through the content tree and into other writable areas.
This vulnerability appears in Grav-based sites that use the API plugin to manage pages through POST /pages/{route}/move.
It is relevant where:
- The
getgrav/grav-plugin-apipackage is deployed below version 1.0.10 - API access with
api.pages.writepermission is granted to users or automation - The underlying filesystem allows the web process to write outside
user/pages/
In such environments, user-supplied slugs are treated as directory paths with insufficient normalization, enabling traversal through the content tree and into other writable areas.
Exploit preconditions
- Attack surface: HTTP API endpoint
POST /pages/{route}/move - Required access: Authenticated API access with
api.pages.writepermission - Trigger point: Supplying a malicious
slug(e.g., with/or..segments) in the JSON request body - Why exploitation is possible: The
PagesController::move()method only strips leading periods vialtrim($body['slug'], '.'), so the slug is still interpreted as a relative filesystem path including/and.., allowing directory traversal and arbitrary move destinations within any writable path.
- Attack surface: HTTP API endpoint
POST /pages/{route}/move - Required access: Authenticated API access with
api.pages.writepermission - Trigger point: Supplying a malicious
slug(e.g., with/or..segments) in the JSON request body - Why exploitation is possible: The
PagesController::move()method only strips leading periods vialtrim($body['slug'], '.'), so the slug is still interpreted as a relative filesystem path including/and.., allowing directory traversal and arbitrary move destinations within any writable path.
Why this happens
The core issue is improper validation and normalization of user-controlled filesystem paths.
Instead of treating the slug as a constrained page identifier, the implementation accepts path-like input and passes it to file operations after only minimal sanitization (removing leading dots).
This maps to CWE-73: External Control of File Name or Path, where untrusted data can select filesystem locations for read/write operations.
The bug pattern is a missing canonicalization and enforcement of a fixed base directory, combined with the absence of checks to prevent .. segments and nested path components in user-provided identifiers.
The core issue is improper validation and normalization of user-controlled filesystem paths.
Instead of treating the slug as a constrained page identifier, the implementation accepts path-like input and passes it to file operations after only minimal sanitization (removing leading dots).
This maps to CWE-73: External Control of File Name or Path, where untrusted data can select filesystem locations for read/write operations.
The bug pattern is a missing canonicalization and enforcement of a fixed base directory, combined with the absence of checks to prevent .. segments and nested path components in user-provided identifiers.
Potential impact
- An authenticated user may move entire page directories, including content and media, outside
user/pages/. - Site content structure can be corrupted or effectively hidden, causing denial of service for specific pages or sections.
- Content and media can be relocated into other writable directories within the Grav hosting environment.
- If other processes or plugins rely on predictable locations, an attacker could disrupt automation, backups, or indexing.
- In some deployments, this may facilitate staging content for further abuse, such as overwriting or confusing file-based workflows.
- An authenticated user may move entire page directories, including content and media, outside
user/pages/. - Site content structure can be corrupted or effectively hidden, causing denial of service for specific pages or sections.
- Content and media can be relocated into other writable directories within the Grav hosting environment.
- If other processes or plugins rely on predictable locations, an attacker could disrupt automation, backups, or indexing.
- In some deployments, this may facilitate staging content for further abuse, such as overwriting or confusing file-based workflows.
General mitigation guidance
Effective mitigation centers on treating slugs as logical identifiers rather than raw filesystem paths and enforcing strict directory boundaries.
Common defensive patterns include:
- Normalizing and canonicalizing user-provided paths before any file operations, then verifying they reside under the intended base directory (e.g.,
user/pages/). - Restricting allowed slug characters and explicitly disallowing
/,\,.., or other path separators in fields that should represent single-page identifiers. - Building destination paths server-side from trusted components, rather than accepting full paths from clients.
- Applying least-privilege filesystem permissions so the web process can only write within designated content directories.
- Designing API operations so that high-level actions (like "move page") are expressed in terms of page IDs or routes, with the server resolving to safe filesystem paths internally.
Effective mitigation centers on treating slugs as logical identifiers rather than raw filesystem paths and enforcing strict directory boundaries.
Common defensive patterns include:
- Normalizing and canonicalizing user-provided paths before any file operations, then verifying they reside under the intended base directory (e.g.,
user/pages/). - Restricting allowed slug characters and explicitly disallowing
/,\,.., or other path separators in fields that should represent single-page identifiers. - Building destination paths server-side from trusted components, rather than accepting full paths from clients.
- Applying least-privilege filesystem permissions so the web process can only write within designated content directories.
- Designing API operations so that high-level actions (like "move page") are expressed in terms of page IDs or routes, with the server resolving to safe filesystem paths internally.
How teams detect issues like this
Organizations can identify similar path traversal issues by:
- Using static analysis rules that flag usage of user-controlled variables in file operations such as
rename(),move(), or directory manipulation without prior normalization and boundary checks. - Reviewing controller and API handler code for patterns where fields like "slug", "name", or "route" are concatenated into filesystem paths.
- Implementing code review checklists that require validation of all path-related parameters, including checks for
..segments and path separators. - Enforcing security policies that mandate canonicalization and base-directory enforcement for any content management operations.
- Applying automated code scanning tools tuned to detect CWE-73 conditions in PHP and other web application codebases.
Organizations can identify similar path traversal issues by:
- Using static analysis rules that flag usage of user-controlled variables in file operations such as
rename(),move(), or directory manipulation without prior normalization and boundary checks. - Reviewing controller and API handler code for patterns where fields like "slug", "name", or "route" are concatenated into filesystem paths.
- Implementing code review checklists that require validation of all path-related parameters, including checks for
..segments and path separators. - Enforcing security policies that mandate canonicalization and base-directory enforcement for any content management operations.
- Applying automated code scanning tools tuned to detect CWE-73 conditions in PHP and other web application codebases.

