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

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

CVE-2026-61451 is an authentication bypass flaw in Grav API plugin that allows attackers to hijack password reset tokens through malicious URL injection. This article covers the technical details, affected versions, and mitigation.

Published:

CVE-2026-61451 Overview

CVE-2026-61451 is an open redirect and host header injection flaw in the Grav API plugin (grav-plugin-api) before version 1.0.4. The plugin fails to validate the origin of the client-supplied admin_base_url field in the POST /api/v1/auth/forgot-password endpoint. An unauthenticated attacker can supply an arbitrary host, causing the password reset email delivered to a victim to contain a reset link pointing to an attacker-controlled server. When the victim clicks the link, the valid reset token is transmitted to the attacker, enabling full account takeover. The vulnerable base URL can also be influenced via the Referer or Origin headers.

Critical Impact

An unauthenticated remote attacker can hijack password reset tokens and take over any Grav account, including administrators, when the victim clicks the poisoned reset link.

Affected Products

  • Grav CMS deployments using grav-plugin-api
  • grav-plugin-api versions prior to 1.0.4
  • Any Grav instance exposing the /api/v1/auth/forgot-password endpoint

Discovery Timeline

  • 2026-07-15 - CVE-2026-61451 published to the National Vulnerability Database (NVD)
  • 2026-07-15 - Last updated in NVD database

Technical Details for CVE-2026-61451

Vulnerability Analysis

The flaw is classified as a URL Redirection to Untrusted Site [CWE-601]. The POST /api/v1/auth/forgot-password endpoint accepts an admin_base_url parameter from the request body and uses it verbatim when constructing the password reset link embedded in the outbound email. The plugin's sanitizeHttpUrl() helper only enforces that the scheme is http or https. It never compares the supplied host against the server's own origin or an allowlist of trusted domains.

Because the endpoint is unauthenticated, any remote party who knows a valid username or email can trigger the reset flow. The reset token generated by the server is legitimate and long-lived enough to allow interactive exploitation. Once the attacker captures the token from their logging server, they can complete the password change and assume control of the victim account.

Root Cause

The root cause is insufficient input validation on a security-sensitive URL field. sanitizeHttpUrl() performs scheme validation but omits host validation. The plugin additionally trusts the Referer and Origin HTTP headers as fallback sources for the base URL, expanding the attack surface to any client that can shape those headers.

Attack Vector

The attacker sends a crafted POST request to /api/v1/auth/forgot-password containing the victim's email or username and an admin_base_url value pointing to a host they control. Alternatively, they can omit the body field and inject the malicious host via the Referer or Origin header. The Grav server then generates a password reset token and emails a link built from the attacker-supplied base URL. When the victim clicks the link, their browser transmits the token to the attacker's endpoint, which then uses it against the legitimate Grav instance to complete the reset. See the GitHub Security Advisory and the Vulncheck Advisory on Grav Vulnerability for further technical detail.

Detection Methods for CVE-2026-61451

Indicators of Compromise

  • Requests to /api/v1/auth/forgot-password where the JSON body contains an admin_base_url value referencing an external or unexpected host.
  • Inbound requests to the forgot-password endpoint with Referer or Origin headers that do not match the server's canonical hostname.
  • Outbound password reset emails containing links whose domain does not match the configured Grav admin URL.
  • Successful password resets shortly after a forgot-password request originating from an unfamiliar IP address.

Detection Strategies

  • Parse web server access logs for POST requests to /api/v1/auth/forgot-password and flag any where the request body or header-derived host differs from the site's canonical origin.
  • Add a mail gateway rule that inspects outbound Grav password reset emails and alerts on links whose hostname deviates from an allowlist.
  • Correlate forgot-password requests with subsequent authentication events from disparate IP addresses within a short time window.

Monitoring Recommendations

  • Centralize Grav web server and application logs into a SIEM or data lake for cross-source correlation of reset flows and authentication events.
  • Baseline the volume and source distribution of forgot-password requests, and alert on anomalies such as bursts against multiple accounts.
  • Review administrator account activity daily for unexpected password changes or session establishment from new geolocations.

How to Mitigate CVE-2026-61451

Immediate Actions Required

  • Upgrade grav-plugin-api to version 1.0.4 or later on all Grav deployments.
  • Rotate credentials for administrator and privileged Grav accounts once patched, particularly if forgot-password traffic anomalies are present.
  • Audit recent password resets and invalidate active sessions to expel any attacker who may already hold tokens.

Patch Information

The maintainers addressed the flaw in grav-plugin-api version 1.0.4 by validating that the host in the reset URL matches the server's own origin. Refer to the GitHub Security Advisory GHSA-5xc4-j99p-cp4m for release notes and upgrade guidance.

Workarounds

  • If immediate upgrade is not possible, place the /api/v1/auth/forgot-password endpoint behind a reverse proxy rule that strips the admin_base_url field and normalizes Referer and Origin headers to the canonical hostname.
  • Restrict access to the API plugin endpoints to trusted networks via IP allowlisting until the patch can be applied.
  • Temporarily disable the API plugin or the password reset feature in high-risk environments while remediation is scheduled.
bash
# Example nginx rule to strip attacker-controlled fields and normalize headers
location = /api/v1/auth/forgot-password {
    proxy_set_header Referer "https://grav.example.com/";
    proxy_set_header Origin  "https://grav.example.com";
    # Drop client-supplied admin_base_url before forwarding
    if ($request_method = POST) {
        set $sanitized_body $request_body;
    }
    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.