Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2025-66307

CVE-2025-66307: Grav Admin Plugin Info Disclosure Flaw

CVE-2025-66307 is an information disclosure vulnerability in Grav Admin Plugin that exposes usernames and email addresses via the Forgot Password feature. This article covers technical details, affected versions, and mitigation.

Updated:

CVE-2025-66307 Overview

CVE-2025-66307 is an information disclosure vulnerability in the Grav admin plugin, an HTML-based interface used to configure Grav CMS and manage pages. The flaw resides in the Forgot Password functionality exposed at /admin/forgot. The endpoint returns distinct server responses depending on whether a submitted username exists, and it discloses the associated email address in certain cases. Attackers can enumerate valid accounts and harvest email addresses without authentication. The disclosed data supports targeted follow-on attacks including password spraying, phishing, and social engineering. The vulnerability is fixed in version 1.11.0-beta.1 [CWE-204: Observable Response Discrepancy].

Critical Impact

Unauthenticated remote attackers can enumerate valid Grav administrator usernames and disclose their associated email addresses through response differences in the password reset flow.

Affected Products

  • Getgrav grav-plugin-admin versions prior to 1.11.0-beta.1
  • Grav CMS installations exposing the /admin/forgot endpoint
  • Any Grav deployment relying on the vulnerable admin plugin login controller

Discovery Timeline

  • 2025-12-01 - CVE-2025-66307 published to the National Vulnerability Database
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2025-66307

Vulnerability Analysis

The vulnerability is an Observable Response Discrepancy in the Grav admin plugin login controller. When a user submits a username or email to /admin/forgot, the application returns different response messages based on whether the account exists and whether it is currently rate-limited. One error path, triggered when the account exists but has exceeded the reset interval, embedded the target email address ($to) directly into the returned message. This behavior confirms account existence and leaks the associated email address to any unauthenticated requester.

Root Cause

The root cause is verbose, state-dependent error messaging in classes/plugin/Controllers/Login/LoginController.php. The translation key PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED accepted the account's email address as a parameter and rendered it in the user-facing response. Combined with distinct responses for valid versus invalid users, this design violated the principle of uniform authentication responses.

Attack Vector

An unauthenticated attacker sends crafted POST requests to /admin/forgot with candidate usernames or email addresses. By comparing response strings, status codes, and rate-limiting messages, the attacker classifies each input as valid or invalid. Repeated rate-limit responses reveal the associated email in the message body. The attack requires only network access to the Grav admin interface and no user interaction.

php
            $interval = $config->get('plugins.login.max_pw_resets_interval', 2);

-            $this->setMessage($this->translate('PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED', $to, $interval), 'error');
+            // Security: Use generic message to prevent email enumeration (GHSA-q3qx-cp62-f6m7)
+            $this->setMessage($this->translate('PLUGIN_ADMIN.FORGOT_CANNOT_RESET_RATE_LIMITED', $interval), 'error');

            return $this->createRedirectResponse($current);
        }

Source: Grav admin plugin patch commit 99f6532. The patch removes the $to (email) argument from the translated message and switches to a generic rate-limit string, eliminating the disclosure.

Detection Methods for CVE-2025-66307

Indicators of Compromise

  • High volumes of POST requests to /admin/forgot originating from a single IP or narrow IP range within a short window.
  • Sequential submissions of common usernames (admin, root, editor) or dictionary-based email addresses against the endpoint.
  • Server responses containing PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED or rendered email addresses returned to unauthenticated clients.
  • Unexpected spikes in plugins.login.max_pw_resets_interval rate-limit triggers in application logs.

Detection Strategies

  • Deploy WAF rules that alert on repeated /admin/forgot submissions exceeding a configurable threshold per source IP.
  • Parse Grav application logs for successive forgot password events referencing multiple distinct usernames from the same session or IP.
  • Correlate /admin/forgot traffic with subsequent phishing or credential-stuffing attempts against the same accounts.

Monitoring Recommendations

  • Enable verbose logging on the Grav admin plugin and forward events to a centralized log platform for retention and analysis.
  • Baseline normal password reset volumes per Grav instance and alert on statistical deviations.
  • Monitor outbound password reset emails for unusual bursts that may indicate active enumeration attempts.

How to Mitigate CVE-2025-66307

Immediate Actions Required

  • Upgrade the grav-plugin-admin package to version 1.11.0-beta.1 or later on all Grav installations.
  • Restrict access to /admin and /admin/forgot to trusted networks or VPN clients while patching is scheduled.
  • Enforce rate limiting and IP throttling on password reset endpoints at the reverse proxy or WAF layer.
  • Review recent web server logs for suspicious enumeration patterns and rotate any exposed admin email addresses where feasible.

Patch Information

The vendor released a fix in commit 99f653296504f1d6408510dd2f6f20a45a26f9b0, included in grav-plugin-admin1.11.0-beta.1. The patch replaces the email-bearing error message with a generic rate-limit response and unifies responses across valid and invalid users. Full details are published in the GitHub Security Advisory GHSA-q3qx-cp62-f6m7 and the upstream patch commit.

Workarounds

  • Place the Grav admin interface behind an authenticated reverse proxy or IP allowlist until the patched plugin is deployed.
  • Configure aggressive rate limits on /admin/forgot to slow enumeration attempts by unauthenticated clients.
  • Customize the PLUGIN_LOGIN.FORGOT_CANNOT_RESET_IT_IS_BLOCKED translation string locally to remove the email placeholder as an interim measure.
bash
# Nginx rate-limiting example for the vulnerable endpoint
limit_req_zone $binary_remote_addr zone=grav_forgot:10m rate=5r/m;

server {
    location = /admin/forgot {
        limit_req zone=grav_forgot burst=2 nodelay;
        allow 10.0.0.0/8;
        deny all;
        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.