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

CVE-2026-63408: Grav API Plugin Information Disclosure

CVE-2026-63408 is an information disclosure vulnerability in Grav API Plugin that exposes JWT tokens through URL parameters in logs and browser history. This article covers technical details, affected versions, and mitigation.

Updated:

CVE-2026-63408 Overview

CVE-2026-63408 is a high-severity information disclosure vulnerability in the Grav API Plugin, a RESTful API for Grav CMS that provides headless access to site content. The JwtAuthenticator::extractBearerToken() method accepts a JSON Web Token (JWT) supplied through the token URL query parameter on every /api/v1 route, including state-changing endpoints. Because tokens appear in URLs, they leak into Apache logs, proxy logs, CDN logs, browser history, and HTTP Referer headers. Any party with access to those records can replay the token with the owner's API privileges. The issue is fixed in version 1.0.0-rc.16.

Critical Impact

Valid JWT access tokens exposed in URLs can be harvested from logs and browser history, enabling attackers to impersonate authenticated API users and access privileged endpoints.

Affected Products

  • Grav API Plugin versions prior to 1.0.0-rc.16
  • Grav CMS deployments exposing the /api/v1 routes with JWT authentication
  • Any downstream integrations relying on the Grav API Plugin for headless content access

Discovery Timeline

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

Technical Details for CVE-2026-63408

Vulnerability Analysis

The Grav API Plugin implements JWT-based authentication through the JwtAuthenticator class. Rather than restricting tokens to the HTTP Authorization header, the plugin also honors a ?token= URL query parameter on every /api/v1 route. This design decision places bearer credentials directly into request URLs.

URLs are logged and cached at multiple layers of typical web infrastructure. Apache access logs, reverse proxy logs, CDN request records, and client-side browser history all persist the full URL, including the JWT. When a browser navigates to an external link from an authenticated page, the token can also leak through the Referer header. This vulnerability is classified as [CWE-598] Use of GET Request Method With Sensitive Query Strings.

Root Cause

The root cause is the acceptance of authentication credentials in URL query strings for all API routes, including sensitive state-changing endpoints. The extractBearerToken() method did not restrict the query-parameter fallback to routes that genuinely require it, such as file downloads or thumbnail streams where a browser element cannot attach an Authorization header.

Attack Vector

An attacker with access to server logs, proxy logs, CDN logs, browser history exports, or referrer traffic captures can extract valid JWTs from URLs. Since JWTs remain valid until expiration, the attacker can replay them against /api/v1 endpoints to read, modify, or delete content with the original owner's privileges. No user interaction or authentication is required to reuse the harvested token.

php
// Patch: Restrict ?token= URL fallback to specific routes
// Source: https://github.com/getgrav/grav-plugin-api/commit/56ae2ca3bf36c8299a4b3d376c6a20e8c0ed5ba9

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,

Detection Methods for CVE-2026-63408

Indicators of Compromise

  • Requests to /api/v1/* endpoints containing a token= query parameter in Apache, Nginx, or CDN access logs
  • Reuse of the same JWT from multiple source IP addresses or user agents within a short window
  • Unexpected state-changing API calls (POST, PUT, DELETE) authenticated via URL-embedded tokens
  • Referer headers in outbound traffic that contain Grav API URLs with embedded tokens

Detection Strategies

  • Parse historical web server and CDN logs for the pattern /api/v1/*?*token=* and flag matching entries for token rotation
  • Correlate JWT identifiers with source IPs to detect tokens replayed from log-harvesting locations
  • Audit third-party CDN and analytics providers to determine whether URLs containing tokens were exported or shared

Monitoring Recommendations

  • Enable alerting on any /api/v1 request that includes a token query parameter after upgrading, since the parameter should only be honored on /download and /thumbnails routes
  • Monitor authentication logs for JWT reuse patterns inconsistent with normal client behavior
  • Review Web Application Firewall (WAF) telemetry for requests carrying bearer tokens in URLs

How to Mitigate CVE-2026-63408

Immediate Actions Required

  • Upgrade the Grav API Plugin to version 1.0.0-rc.16 or later
  • Invalidate all existing JWTs and force re-issuance, since previously issued tokens may have leaked into logs
  • Purge or restrict access to historical Apache, proxy, and CDN logs that may contain URL-embedded tokens
  • Review and clear browser history and cached referrer data on administrative workstations

Patch Information

The fix is available in Grav API Plugin 1.0.0-rc.16. See the GitHub Release 1.0.0-rc.16, the security commit, and the GitHub Security Advisory GHSA-4hpj-wmpw-ghwq for details. The patch restricts the ?token= URL fallback to /download and /thumbnails routes only.

Workarounds

  • Configure a reverse proxy or WAF rule to strip the token query parameter from all /api/v1 requests except /download and /thumbnails
  • Require the Authorization: Bearer <token> header for API authentication and reject requests carrying tokens in query strings
  • Reduce JWT lifetime to limit the replay window if immediate patching is not possible
bash
# Example Nginx rule to block JWTs in query strings on non-download routes
location ~ ^/api/v1/(?!.*/(download|thumbnails)) {
    if ($arg_token) {
        return 400 "token query parameter not permitted on this route";
    }
    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.