Executive brief
The Grav API plugin's password reset feature trusts the HTTP Host header to build password reset links sent to users' email addresses. An attacker can send a password reset request for any account while spoofing the Host header to point to their own domain, causing the victim to receive a reset link that redirects to the attacker's server. The attacker can then capture the reset token and take over any account, including super-admin accounts that grant full control of the Grav site.
Technical details
The vulnerability is an authentication bypass stemming from improper use of untrusted user input (the HTTP Host header) to construct password reset URLs. In the POST /api/v1/auth/forgot-password endpoint, the Grav API plugin builds the password reset link from $_SERVER['HTTP_HOST'] without validation, and includes a reset token in the URL query string. An unauthenticated attacker can send a forgot-password request with an arbitrary Host header pointing to attacker-controlled infrastructure. The victim receives a legitimate reset email from the legitimate site, but the link in the email points to the attacker's domain and carries a valid, server-side token. When the victim clicks the link, the attacker reads the token from their access logs and completes the reset via POST /api/v1/auth/reset-password, taking over the account. No preconditions (authentication, session, special config) are required; only that the server answers requests for arbitrary Host values (standard Apache/Nginx default behavior). Patched in version 1.0.20.
Affected products
- Grav API Plugin before 1.0.20
Timeline
- 2026-08-21: disclosed: GHSA-262p-56vv-7v5r published
- 2026-09-05: disclosed: CVE-2026-86196 published on NVD
- 2026: patched: Fixed in Grav API Plugin 1.0.20