CVE-2025-52898 Overview
CVE-2025-52898 is an Information Exposure vulnerability affecting the Frappe full-stack web application framework. The vulnerability allows a malicious actor to gain access to a user's password reset token through a carefully crafted request. This security flaw exists in versions prior to 14.94.3 and 15.58.0 and specifically impacts self-hosted Frappe instances configured in a certain way. Frappe Cloud users are not affected by this vulnerability.
Critical Impact
Attackers can intercept password reset tokens, enabling unauthorized account takeover on vulnerable self-hosted Frappe instances through Host header manipulation.
Affected Products
- Frappe Framework versions prior to 14.94.3
- Frappe Framework versions prior to 15.58.0
- Self-hosted Frappe instances with vulnerable configurations
Discovery Timeline
- June 30, 2025 - CVE-2025-52898 published to NVD
- July 8, 2025 - Last updated in NVD database
Technical Details for CVE-2025-52898
Vulnerability Analysis
This vulnerability stems from improper handling of the Host header when generating password reset URLs. The get_url() function in the Frappe framework allowed HTTP Host header values to override the configured hostname when constructing URLs. When a user requests a password reset, the system generates a reset link containing a sensitive token. An attacker could manipulate the Host header in the password reset request to point to an attacker-controlled domain, causing the generated reset link to use the malicious domain instead of the legitimate one.
When the victim receives the password reset email and clicks the link, their password reset token is transmitted to the attacker's server, allowing the attacker to use that token on the legitimate Frappe instance to reset the victim's password and take over their account.
Root Cause
The root cause lies in the get_url() utility function located in frappe/utils/data.py. This function was designed to construct application URLs from incoming requests but did not properly restrict Host header override behavior for security-sensitive operations. The password reset flow in frappe/core/doctype/user/user.py called get_url() without any protection against Host header manipulation, allowing attackers to inject arbitrary domains into password reset emails.
Attack Vector
The attack requires network access and user interaction. An attacker crafts a password reset request for a target user while injecting a malicious Host header pointing to their controlled domain. The Frappe instance generates a password reset email containing a link with the attacker's domain. When the victim clicks this link expecting to reset their password, the reset token (contained in the URL's key parameter) is sent to the attacker's server, which can then capture and use it.
# Security patch in frappe/core/doctype/user/user.py
# Source: https://github.com/frappe/frappe/commit/52e31337a6c964189c8b883a2f7bc3a28ab374f2
if password_expired:
url = "/update-password?key=" + key + "&password_expired=true"
- link = get_url(url)
+ link = get_url(url, allow_header_override=False)
if send_email:
self.password_reset_mail(link)
# Security patch in frappe/utils/data.py - Updated get_url function signature
# Source: https://github.com/frappe/frappe/commit/52e31337a6c964189c8b883a2f7bc3a28ab374f2
return (cstr(sep)).join(cstr(a).strip() for a in filter(None, some_list))
-def get_url(uri: str | None = None, full_address: bool = False) -> str:
- """get app url from request"""
+def get_url(
+ uri: str | None = None,
+ full_address: bool = False,
+ allow_header_override: bool = True,
+) -> str:
+ """Get app url from request."""
host_name = frappe.local.conf.host_name or frappe.local.conf.hostname
if uri and (uri.startswith("http://") or uri.startswith("https://")):
Detection Methods for CVE-2025-52898
Indicators of Compromise
- Password reset emails containing unexpected or malicious domain names in reset links
- Web server logs showing password reset requests with suspicious or unfamiliar Host header values
- Users reporting password reset emails with links pointing to domains other than your Frappe instance
- Authentication logs showing successful password resets without legitimate user activity
Detection Strategies
- Monitor HTTP access logs for password reset endpoint requests (/api/method/frappe.core.doctype.user.user.reset_password) with Host headers not matching your configured domain
- Implement alerting for outbound emails containing URLs with domains different from the expected application domain
- Review email delivery logs for password reset notifications and validate the URLs within them
- Deploy Web Application Firewall (WAF) rules to detect and block requests with manipulated Host headers
Monitoring Recommendations
- Enable detailed logging for the password reset workflow in Frappe
- Configure alerts for any password reset requests originating from IP addresses with suspicious Host header values
- Implement email security controls to flag outbound messages containing links to unrecognized domains
- Regularly audit Frappe version deployments to ensure patched versions are in use
How to Mitigate CVE-2025-52898
Immediate Actions Required
- Upgrade Frappe Framework to version 14.94.3 or 15.58.0 or later immediately
- Review recent password reset logs for any suspicious activity or compromised accounts
- Force password resets for any accounts suspected of being compromised
- Verify the host_name configuration in your Frappe site_config.json is properly set
Patch Information
Frappe has released security patches addressing this vulnerability in versions 14.94.3 and 15.58.0. The fix introduces a new allow_header_override parameter to the get_url() function and explicitly disables header override when generating password reset URLs. Self-hosted users should upgrade immediately by following the standard Frappe update procedures.
For detailed patch information, see the GitHub Security Advisory GHSA-p284-r7rh-wq7j and the associated Pull Request #31522.
Workarounds
- Educate users to verify password reset URLs before clicking, ensuring they point to the legitimate Frappe instance domain
- Configure your reverse proxy or load balancer to validate and enforce the Host header matches your expected domain
- Temporarily disable the password reset functionality if immediate patching is not possible
- Implement email security warnings for links pointing to unexpected domains
# Configuration example - Verify and set host_name in Frappe site config
cd /path/to/frappe-bench
bench --site yoursite.local set-config host_name "https://yoursite.example.com"
# Upgrade Frappe to patched version
bench update --apps frappe
bench --site yoursite.local migrate
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

