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

CVE-2026-53654: Grav Login Plugin Auth Bypass Vulnerability

CVE-2026-53654 is an authentication bypass flaw in Grav's Login plugin that enables phishing attacks through unvalidated redirects. This post covers the technical details, affected versions, security impact, and mitigation.

Updated:

CVE-2026-53654 Overview

CVE-2026-53654 is an open redirect vulnerability [CWE-601] in the Grav Login plugin affecting versions prior to 3.8.5. The twofa_cancel task accepts a client-controlled _redirect field without validating a nonce. An unauthenticated attacker can supply an external http, https, or protocol-relative URL as the redirect target. Controller::execute() applies the field when taskTwofa_cancel() sets no redirect, and Grav::getRedirectResponse() accepts the target through Uri::isExternal(). The result: attackers can craft links on a trusted Grav host that redirect victims to attacker-controlled phishing sites.

Critical Impact

Unauthenticated attackers can leverage a trusted Grav domain to redirect users to arbitrary external URLs, enabling credential phishing and malware distribution campaigns.

Affected Products

  • Grav CMS Login plugin versions prior to 3.8.5
  • Grav file-based Web platform deployments using the Login plugin
  • Sites relying on the plugin's two-factor authentication (2FA) flow

Discovery Timeline

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

Technical Details for CVE-2026-53654

Vulnerability Analysis

The Grav Login plugin exposes a twofa_cancel task used to abort an in-progress two-factor authentication challenge. Prior to version 3.8.5, this task did not verify the login-form nonce that guards other login tasks. The handler processes a _redirect POST field supplied by the client without validating its origin. When taskTwofa_cancel() completes without explicitly setting a redirect, Controller::execute() falls back to the client-supplied value. Grav then issues an HTTP 303 response pointing to the attacker-controlled target. Because the redirect originates from a legitimate Grav host, users and security tools are more likely to trust it. The classification aligns with URL Redirection to Untrusted Site [CWE-601].

Root Cause

Two control gaps combine to produce the flaw. First, twofa_cancel was omitted from the nonce verification switch in login.php, allowing unauthenticated invocation. Second, the fallback redirect logic in classes/Controller.php accepted any _redirect value, including external URLs approved by Uri::isExternal() as a routable target rather than rejected.

Attack Vector

An attacker crafts a URL or form pointing at the Grav site's login endpoint with task=twofa_cancel and _redirect=https://attacker.example/phish. The victim clicks the link on the trusted Grav domain. Grav processes the request without nonce verification and issues a 303 redirect to the attacker's page. User interaction is required, consistent with phishing scenarios.

php
// Patch in classes/Controller.php — reject off-site _redirect targets
            $this->grav['log']->error('plugin.login: '. $e->getMessage());
        }

-        if (!$this->redirect && $redirect) {
+        // Never honor a client-supplied `_redirect` that points off-site. This
+        // closes the open-redirect across every login task (e.g. `twofa_cancel`,
+        // which returns without setting its own redirect), not just the one that
+        // was reported. Server-side redirects set by a task are unaffected.
+        if (!$this->redirect && $redirect && !Uri::isExternal($redirect)) {
            $this->setRedirect($redirect, 303);
        }

Source: Grav Login plugin commit 1535e51

php
// Patch in login.php — enforce nonce on twofa_cancel
            return;
        }
        break;
+
+    case 'twofa_cancel':
+        // The 2FA form carries the `login-form` nonce, so verify it here
+        // too — `twofa_cancel` was previously unguarded, letting it run
+        // (and act on a client `_redirect`) without a nonce.
+        if (!isset($post['login-form-nonce']) || !Utils::verifyNonce($post['login-form-nonce'], 'login-form')) {
+            $this->grav['messages']->add($this->grav['language']->translate('PLUGIN_LOGIN.ACCESS_DENIED'), 'info');
+            return;
+        }
+        break;
}

$controller = new Controller($this->grav, $task, $post);

Source: Grav Login plugin commit 1535e51

Detection Methods for CVE-2026-53654

Indicators of Compromise

  • Requests to Grav login endpoints containing task=twofa_cancel combined with a _redirect parameter pointing to an external host or protocol-relative URL.
  • HTTP 303 responses from a Grav host with a Location header targeting a domain outside the site's allow list.
  • Referrer traffic in web logs showing users arriving at unknown external domains via the Grav login path.

Detection Strategies

  • Inspect web server access logs for POST or GET requests to the Login plugin task endpoint where _redirect contains http://, https://, or a leading //.
  • Alert on twofa_cancel invocations missing a valid login-form-nonce parameter.
  • Correlate outbound redirect responses with reputation data on the destination host.

Monitoring Recommendations

  • Enable verbose logging on the Grav Login plugin and forward events to a centralized log platform for correlation.
  • Baseline normal 2FA cancellation volume and alert on spikes or requests from unauthenticated sessions.
  • Monitor phishing intelligence feeds for lookalike domains referencing the organization's Grav-hosted site.

How to Mitigate CVE-2026-53654

Immediate Actions Required

  • Upgrade the Grav Login plugin to version 3.8.5 or later on all Grav installations.
  • Audit web logs for prior exploitation attempts referencing twofa_cancel with external _redirect values.
  • Educate users about phishing links that appear to originate from the organization's trusted Grav domain.

Patch Information

The fix is available in Grav Login plugin 3.8.5. The patch adds Uri::isExternal($redirect) checks in Controller::execute() and adds nonce verification for the twofa_cancel task in login.php. Details are published in the GitHub Security Advisory GHSA-wwcc-xxhc-44j6 and the 3.8.5 release notes.

Workarounds

  • Deploy a web application firewall (WAF) rule that blocks requests to the Login plugin endpoint when _redirect contains an absolute or protocol-relative URL.
  • Restrict access to the Grav admin and login endpoints by source IP where feasible until the plugin is upgraded.
  • Strip or rewrite the _redirect parameter at a reverse proxy for task=twofa_cancel requests.
bash
# Example ModSecurity rule to block external _redirect values on twofa_cancel
SecRule ARGS:task "@streq twofa_cancel" \
    "id:1005301,phase:2,chain,deny,status:400,log,msg:'CVE-2026-53654 open redirect attempt'"
    SecRule ARGS:_redirect "@rx ^(https?:)?//" "t:none"

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.