Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-75830

CVE-2026-75830: Grav Plugin API Path Traversal Vulnerability

CVE-2026-75830 is a path traversal flaw in Grav Plugin API that allows authenticated editors to write files to arbitrary filesystem locations. This post explains its technical details, affected versions, and mitigation steps.

Published:

CVE-2026-75830 Overview

CVE-2026-75830 is a path traversal vulnerability [CWE-73] in the grav-plugin-api component of the Grav content management system. The flaw affects getgrav/grav-plugin-api versions >= 1.0.0-beta.10 and <= 1.0.14. It resides in the PagesController::batchCopy() method, which fails to validate the user-controlled suffix parameter submitted via POST /api/v1/pages/batch. An incomplete fix for the prior advisory GHSA-qjq4-jp55-4mx2 left this parameter exploitable. Authenticated users holding the api.pages.write permission at editor level can supply traversal sequences to write attacker-controlled content outside the intended pages directory.

Critical Impact

Authenticated editor-level users can write arbitrary page content and page media to any filesystem location writable by the web server process, enabling code deployment and site compromise without super-admin privileges.

Affected Products

  • getgrav/grav-plugin-api versions >= 1.0.0-beta.10
  • getgrav/grav-plugin-api versions <= 1.0.14
  • Grav CMS deployments exposing the batch pages API endpoint

Discovery Timeline

  • 2026-08-18 - CVE-2026-75830 published to the National Vulnerability Database (NVD)
  • 2026-08-18 - Last updated in NVD database

Technical Details for CVE-2026-75830

Vulnerability Analysis

The vulnerability resides in the PagesController::batchCopy() handler exposed through the Grav REST API. When an authenticated caller invokes POST /api/v1/pages/batch to copy pages, the controller accepts a suffix parameter used to derive the destination path. The batchCopy logic does not sanitize this parameter or reject directory traversal sequences.

A prior advisory (GHSA-qjq4-jp55-4mx2) addressed related traversal issues, but the remediation was incomplete and left the suffix field unvalidated in the batch copy path. Because the API accepts network requests and requires only editor-level authorization, exploitation reduces to a single crafted HTTP request from any account holding api.pages.write.

Root Cause

The root cause is improper limitation of a pathname to a restricted directory, tracked as [CWE-73] (External Control of File Name or Path). The suffix value is concatenated into the destination path without canonicalization or a boundary check against the intended user/pages/ directory. Traversal segments such as /../../../ collapse the path outside the pages root when the filesystem resolves the write operation.

Attack Vector

Exploitation requires an authenticated session with the api.pages.write permission — a standard editor role, not super-admin. The attacker issues a POST request to /api/v1/pages/batch invoking the copy operation and supplies a suffix value containing traversal sequences. Grav then writes attacker-controlled page content and page media to arbitrary paths writable by the web server user. Attackers can leverage this to drop PHP files into web-served directories, overwrite configuration under user/config/, or plant persistence artifacts.

No verified proof-of-concept code has been published. See the GitHub Security Advisory and the VulnCheck Advisory for vendor-supplied technical details.

Detection Methods for CVE-2026-75830

Indicators of Compromise

  • HTTP POST requests to /api/v1/pages/batch where the JSON body contains suffix values including ../, ..\, or URL-encoded equivalents such as %2e%2e%2f.
  • New or modified files under directories outside user/pages/ — particularly user/config/, user/plugins/, or the webroot — with ownership matching the PHP or web server process user.
  • Unexpected .md, .php, or media files timestamped shortly after batch API calls from editor accounts.

Detection Strategies

  • Inspect web server and application logs for requests to the batch endpoint containing traversal patterns in request bodies.
  • Enable file integrity monitoring across the entire Grav installation, not only user/pages/, to catch writes into unexpected directories.
  • Correlate authenticated editor sessions with subsequent filesystem changes outside their expected working directory.

Monitoring Recommendations

  • Forward Grav application logs and web server access logs to a centralized analytics platform for retention and query.
  • Alert on any write activity by the web server user targeting paths outside user/pages/.
  • Review the population of accounts holding api.pages.write and monitor sessions from those accounts for anomalous API usage.

How to Mitigate CVE-2026-75830

Immediate Actions Required

  • Upgrade grav-plugin-api to version 1.0.15 or later, which contains the corrected input validation.
  • Audit all accounts holding the api.pages.write permission and revoke access from users who do not require content editing.
  • Restrict network exposure of /api/v1/pages/batch to trusted management networks or place it behind a VPN.

Patch Information

The vulnerability is fixed in grav-plugin-api version 1.0.15. The patch adds validation of the suffix parameter in PagesController::batchCopy() to prevent path traversal outside the pages directory. Refer to the GitHub Security Advisory for commit-level fix details.

Workarounds

  • Disable the grav-plugin-api plugin until upgrade to 1.0.15 is completed.
  • Configure a reverse proxy or web application firewall rule to block requests to /api/v1/pages/batch containing .. sequences in the request body.
  • Constrain filesystem permissions so the web server process cannot write outside user/pages/ and required cache directories.
bash
# Example WAF rule pattern to block traversal in batch API payloads
# (adapt syntax to your WAF vendor)
SecRule REQUEST_URI "@streq /api/v1/pages/batch" \
    "chain,phase:2,deny,status:400,id:2026075830,\
     msg:'CVE-2026-75830 Grav batchCopy path traversal attempt'"
  SecRule REQUEST_BODY "@rx (\.\.[\\/]|%2e%2e(%2f|%5c))" "t:lowercase,t:urlDecodeUni"

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.