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

CVE-2026-63407: Grav API Plugin Auth Bypass Vulnerability

CVE-2026-63407 is an authentication bypass flaw in Grav API Plugin that allows attackers to exploit permissive CORS settings and perform unauthorized operations. This article covers technical details, affected versions, and mitigation.

Updated:

CVE-2026-63407 Overview

CVE-2026-63407 is a permissive cross-origin resource sharing (CORS) misconfiguration [CWE-942] in the Grav API Plugin, a RESTful API that provides headless access to Grav CMS content. Versions prior to 1.0.0-rc.16 return Access-Control-Allow-Origin: * alongside permissive OPTIONS responses for authenticated /api/v1 endpoints. JavaScript running on any attacker-controlled origin can submit a stolen JSON Web Token (JWT) through the Authorization or X-API-Token header, read authenticated responses, and perform write operations with the token owner's privileges. The flaw enables data exfiltration and account modification when an attacker obtains a valid token.

Critical Impact

Cross-origin authenticated requests allow attackers to exfiltrate content and modify accounts by replaying obtained JWTs from arbitrary origins.

Affected Products

  • Grav CMS API Plugin versions prior to 1.0.0-rc.16
  • Grav sites exposing /api/v1 endpoints with the vulnerable CorsMiddleware
  • Headless Grav deployments relying on JWT authentication

Discovery Timeline

  • 2026-08-19 - CVE-2026-63407 published to NVD
  • 2026-08-19 - Last updated in NVD database

Technical Details for CVE-2026-63407

Vulnerability Analysis

The Grav API Plugin's CorsMiddleware returns a wildcard Access-Control-Allow-Origin: * header on authenticated /api/v1 responses. The middleware also emits permissive preflight (OPTIONS) responses without validating the requesting origin. Because the plugin authenticates callers using JWT-bearing headers rather than cookies, browsers treat the credentialed cross-origin request as legitimate. Attacker-controlled JavaScript hosted on any domain can therefore read authenticated JSON responses and issue state-changing writes.

The vulnerability is compounded by the plugin honoring a ?token= query parameter fallback for JWT authentication on routes that were not restricted to file-streaming endpoints. This combination allows tokens leaked through URLs, referrers, or logs to be replayed from any origin.

Root Cause

The root cause is a permissive CORS policy [CWE-942] combined with a broadly accepted URL-based token fallback. The preflight handler did not receive the request context, so origin validation could not be enforced per-request.

Attack Vector

An attacker lures an authenticated Grav API user, or obtains a JWT through a secondary leak such as a referrer header or shared URL. The attacker then hosts JavaScript that issues cross-origin fetch calls to the target /api/v1 endpoints, attaching the token via the Authorization or X-API-Token header. Because the server replies with Access-Control-Allow-Origin: *, the browser exposes the response body to the attacker's script, enabling exfiltration and privileged writes.

php
// Security patch in classes/Api/ApiRouter.php
// Fix cross-origin account takeover via CORS wildcard + JWT in URL

            // Handle CORS preflight
            if ($request->getMethod() === 'OPTIONS') {
-                return (new CorsMiddleware($this->config))->createPreflightResponse();
+                return (new CorsMiddleware($this->config))->createPreflightResponse($request);
            }

            // Require and apply Grav environment

Source: GitHub Commit 56ae2ca

php
// Security patch in classes/Api/Auth/JwtAuthenticator.php
// Restrict URL token fallback to file-streaming routes

class JwtAuthenticator implements AuthenticatorInterface
{
+    /**
+     * Path segments/suffixes on which the `?token=` URL fallback is honored.
+     * These are the only routes that stream a file body to a browser element
+     * that can't attach an auth header. See {@see isTokenQueryAllowed()}.
+     */
+    protected const TOKEN_QUERY_ROUTES = [
+        '/download',     // e.g. /system/backups/{filename}/download
+        '/thumbnails',   // e.g. /thumbnails/{file}
+    ];
+
    public function __construct(
        protected readonly Grav $grav,
        protected readonly Config $config,

Source: GitHub Commit 56ae2ca

Detection Methods for CVE-2026-63407

Indicators of Compromise

  • HTTP responses from /api/v1 endpoints containing Access-Control-Allow-Origin: * alongside Authorization or X-API-Token request headers.
  • Successful authenticated OPTIONS preflight responses that accept arbitrary Origin values.
  • Unexpected write operations (POST, PUT, DELETE) to /api/v1 from user agents whose Referer or Origin headers do not match approved application domains.

Detection Strategies

  • Inspect web server and reverse proxy logs for cross-origin requests to /api/v1 with credentialed headers originating outside allowlisted domains.
  • Monitor for JWTs appearing in URL query parameters (?token=) on routes other than /download or /thumbnails.
  • Correlate account modification events with recent cross-origin API traffic bearing the same token identifier.

Monitoring Recommendations

  • Enable verbose logging on the Grav API Plugin and forward events to a centralized analytics platform for correlation.
  • Alert on repeated OPTIONS preflight requests to /api/v1 from unusual origins, which typically precede exploitation.
  • Track JWT issuance and usage patterns to identify tokens replayed from multiple origins within short time windows.

How to Mitigate CVE-2026-63407

Immediate Actions Required

  • Upgrade the Grav API Plugin to version 1.0.0-rc.16 or later without delay.
  • Revoke and reissue any JWTs that may have been exposed through URLs, referrers, or third-party logs.
  • Audit /api/v1 traffic since deployment for cross-origin write operations and unauthorized account changes.

Patch Information

The fix is released in Grav API Plugin 1.0.0-rc.16. The patch passes the request into CorsMiddleware::createPreflightResponse() so preflight responses can validate the Origin header, and it restricts the ?token= URL fallback to /download and /thumbnails routes. See the GitHub Release 1.0.0-rc.16 and the GitHub Security Advisory GHSA-93px-98wh-6fj2 for full details.

Workarounds

  • Place the API behind a reverse proxy that strips or rewrites Access-Control-Allow-Origin to an explicit allowlist until the patch is applied.
  • Enforce short JWT lifetimes and require rotation to limit the window during which a stolen token can be replayed cross-origin.
  • Block OPTIONS and credentialed /api/v1 requests whose Origin header does not match the site's own domain at the WAF layer.
bash
# Example nginx override enforcing an explicit CORS allowlist for /api/v1
location /api/v1/ {
    set $cors_origin "";
    if ($http_origin = "https://app.example.com") {
        set $cors_origin $http_origin;
    }
    add_header Access-Control-Allow-Origin $cors_origin always;
    add_header Vary Origin always;

    if ($request_method = OPTIONS) {
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE" always;
        add_header Access-Control-Allow-Headers "Authorization, X-API-Token, Content-Type" always;
        return 204;
    }

    proxy_pass http://grav_backend;
}

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.