/

CVE-2026-65896

Severity:

HIGH RISK

(7.1)

Path Traversal (CWE-73) in Grav API move endpoint

CVE-2026-65896

Deferred

Vulnerability type

Category:

Path Traversal / Improper File Path Handling

CWE:

CWE-73

Impact:

Arbitrary File Move / Content Relocation

Severity:

HIGH RISK

(7.1)

CVSS version:

3.1

Catch this CVE while code is being written

Detect vulnerable code directly in pull requests, so CVEs are fixed before merge.

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-api package is deployed below version 1.0.10
  • API access with api.pages.write permission 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-api package is deployed below version 1.0.10
  • API access with api.pages.write permission 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.write permission
  • 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 via ltrim($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.write permission
  • 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 via ltrim($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.

Sources

SourceLink
github.comgithub.com/getgrav/grav/commit/f9438d4e71389b1041ac60b69b0b5714ecfa3bdd
github.comgithub.com/getgrav/grav/security/advisories/GHSA-qjq4-jp55-4mx2
vulncheck.comvulncheck.com/advisories/grav-api-plugin-before-path-traversal-via-move

Frequently asked

questions

It is exploitable over the network through the Grav API, but only by clients that can authenticate and obtain the api.pages.write permission. It is not a purely unauthenticated remote attack.

The attacker needs valid credentials and an API token or session that grants access to the page write API. Without that permission, they cannot invoke the vulnerable move operation.

The safest fix is to treat slugs and similar identifiers as logical names, not raw paths, and to construct actual filesystem paths exclusively from trusted, server-side data. Inputs must be normalized, checked for forbidden characters and .. segments, and enforced to stay under a fixed base directory before any file operation.

Developers can adopt consistent path-handling utilities that encapsulate canonicalization and boundary checks, document clear rules for which fields may contain paths, and include automated tests and static analysis focused on CWE-73 and path traversal patterns as part of their secure development lifecycle.

It is exploitable over the network through the Grav API, but only by clients that can authenticate and obtain the api.pages.write permission. It is not a purely unauthenticated remote attack.

The attacker needs valid credentials and an API token or session that grants access to the page write API. Without that permission, they cannot invoke the vulnerable move operation.

The safest fix is to treat slugs and similar identifiers as logical names, not raw paths, and to construct actual filesystem paths exclusively from trusted, server-side data. Inputs must be normalized, checked for forbidden characters and .. segments, and enforced to stay under a fixed base directory before any file operation.

Developers can adopt consistent path-handling utilities that encapsulate canonicalization and boundary checks, document clear rules for which fields may contain paths, and include automated tests and static analysis focused on CWE-73 and path traversal patterns as part of their secure development lifecycle.

Find out what's already
exploitable in your codebase.