CVE-2025-65924
Executive Summary
CVE-2025-65924 is a stored HTML injection vulnerability in ERPNext, an open-source ERP system, affecting versions up to and including 15.88.1. The flaw resides in the "Add Quality Goal" function, where user-supplied input is not sanitized for HTML tags, specifically <a> hyperlinks. While JavaScript execution is blocked (preventing traditional XSS), the injected HTML is preserved when the system generates a PDF document. This allows an attacker to embed malicious clickable links within a PDF that is generated by the ERP system. Because PDFs from the ERP are generally trusted by users, this creates a high-risk phishing vector. The vulnerability has a low CVSS score due to the requirement for user interaction and the lack of direct data compromise, but the social engineering potential is significant.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability is in the ERPNext application itself, not in a specific package manager (NPM, PyPI, Go, Ruby). The risk is to organizations using ERPNext as a managed service or self-hosted instance. The supply chain risk is indirect: an attacker who compromises a low-privileged user account can use this flaw to distribute malicious links to other users within the same organization.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) - The attacker can inject the malicious link remotely.
- Attack Complexity (AC): Low (L) - No special conditions are required.
- Privileges Required (PR): Low (L) - The attacker needs a valid user account with access to the Quality Goal function.
- User Interaction (UI): Required (R) - The victim must click the link in the PDF.
- Scope (S): Changed (C) - The impact is on the user's browser/system, not the ERP server.
- Confidentiality (C): None (N) - No direct data breach.
- Integrity (I): Low (L) - The attacker can redirect the user to a malicious site.
- Availability (A): None (N) - No impact on system availability.
Threat Level: Medium. While the CVSS score is low (3.0), the real-world risk is elevated due to the trust users place in ERP-generated PDFs. This is a classic phishing enabler.
Deep Dive & Mechanics
The vulnerability is a classic case of HTML injection with a twist. The "Add Quality Goal" form in ERPNext has fields intended for plain text input. The application fails to sanitize or strip HTML tags, specifically <a> (anchor) tags, from this input. When the system generates a PDF document (e.g., a Quality Goal report), it renders the user-supplied HTML directly into the PDF.
The key detail is that JavaScript is blocked. This means the attacker cannot execute arbitrary scripts (XSS). However, they can inject a fully functional hyperlink:
<a href="http://malicious-site.com">Click here for important update</a>
When the PDF is generated, this link becomes a clickable element. Since the PDF is generated by the trusted ERP system, users are highly likely to click it, believing it to be a legitimate link. This can lead to credential harvesting (phishing) or malware delivery.
The attack flow:
- Attacker logs into ERPNext with a low-privileged account.
- Attacker navigates to the "Add Quality Goal" function.
- Attacker enters a malicious
<a>tag in a plain text field (e.g., "Goal Description"). - The system saves the input and later generates a PDF report.
- A victim user opens the PDF and clicks the malicious link.
- The victim is redirected to an attacker-controlled site.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual): The vulnerable code likely does not sanitize the input before storing it in the database or rendering it in the PDF. A simplified example:
# Vulnerable: No sanitization
goal_description = request.form['description']
save_to_database(goal_description)
# Later, when generating PDF:
pdf.add_html(goal_description) # Renders HTML directly
Patched Code (Conceptual): The fix would involve stripping or escaping HTML tags from plain text fields before storage or rendering. A secure implementation:
# Patched: Sanitize input
import bleach
goal_description = bleach.clean(request.form['description'], tags=[], strip=True)
save_to_database(goal_description)
# Or, when rendering PDF, escape HTML:
from markupsafe import escape
pdf.add_text(escape(goal_description)) # Renders as plain text
The patch should ensure that only allowed tags (if any) are permitted, and that <a> tags are either removed or rendered as plain text.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- A valid ERPNext user account with access to the "Quality Goal" function.
- A publicly accessible server to host a phishing page or malware.
Steps:
- Log in to ERPNext.
- Navigate to the "Quality Goal" module.
- Create a new Quality Goal.
- In a plain text field (e.g., "Goal Description"), enter the following payload:
<a href="http://attacker-controlled-server.com/evil">Click here for mandatory training</a> - Save the Quality Goal.
- Trigger the PDF generation (e.g., by printing or exporting the report).
- Distribute the PDF to target users via email or internal messaging.
- When a user clicks the link, they are redirected to your server.
Advanced Payload: To make the link appear more legitimate, use a URL shortener or a subdomain that mimics the organization's domain:
<a href="http://company-update.attacker.com">Mandatory Security Update</a>
Blue Team (Detection & Defense)
Detection:
- Monitor for unusual
<a>tags in plain text fields in ERPNext logs. - Use a Web Application Firewall (WAF) to block HTML tags in form fields that should only accept plain text.
- Implement Content Security Policy (CSP) headers for the ERPNext web interface to restrict inline content.
Defense:
- Apply input validation and sanitization on the server side. Use a library like
bleach(Python) to strip all HTML tags from plain text fields. - If HTML is required in some fields, use a strict allowlist of tags and attributes.
- Educate users to be cautious of links in PDFs, even if they appear to come from the ERP system.
- Monitor for anomalous outbound network connections from user workstations.
Indicators of Compromise (IOCs)
- Network IOCs:
- Outbound connections to unusual or suspicious domains from user workstations.
- PDF files containing
<a>tags with external URLs.
- Host IOCs:
- User browser history showing visits to phishing sites.
- Malware downloads from links in ERP-generated PDFs.
- Application IOCs:
- ERPNext database entries in the
tabQuality Goaltable (or similar) containing HTML tags in plain text fields. - Log entries showing creation of Quality Goals with unusual content.
- ERPNext database entries in the
Detection Engineering
YARA Rule
rule CVE_2025_65924_ERPNext_HTML_Injection {
meta:
description = "Detects PDF files generated by ERPNext containing malicious hyperlinks"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-65924"
strings:
$pdf_header = "%PDF-"
$erpnext_ref = "ERPNext"
$anchor_tag = /<a\s+href\s*=\s*["']http[^"']*["']\s*>/i
condition:
$pdf_header at 0 and $erpnext_ref and $anchor_tag
}
Sigma Rule
title: ERPNext PDF with Malicious Hyperlink
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects creation of PDF files from ERPNext containing suspicious hyperlinks
author: Valters IT
date: 2025-04-10
logsource:
category: file_event
product: windows
detection:
selection:
EventID: 11 # FileCreate
TargetFilename|endswith: '.pdf'
TargetFilename|contains: 'ERPNext'
filter:
TargetFilename|contains: '\\Temp\\' # Exclude temp files
condition: selection and not filter
falsepositives:
- Legitimate use of hyperlinks in PDFs
level: medium
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-65924 - ERPNext PDF Malicious Link"; flow:to_server,established; content:"GET"; http_method; content:"/api/method/erpnext.quality_goal"; http_uri; content:"<a"; http_client_body; pcre:"/<a\s+href\s*=\s*["']http/i"; classtype:attempted-user; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade ERPNext: Check for a patched version (15.88.2 or later) and apply it immediately.
- Input Validation: If patching is not possible, implement a custom middleware or hook to sanitize input for the Quality Goal function. Strip all HTML tags from plain text fields.
- User Awareness: Send a security alert to all users warning them about the risk of clicking links in ERP-generated PDFs.
Long-Term Fixes:
- Code Review: Conduct a thorough code review of all input handling functions in ERPNext to identify similar vulnerabilities.
- Security Testing: Integrate automated security scanning (SAST/DAST) into the CI/CD pipeline.
- Web Application Firewall: Deploy a WAF with rules to block HTML tags in form fields that should only accept plain text.
Workarounds:
- Disable the PDF generation feature for the Quality Goal module until a patch is applied.
- Use a proxy to inspect and sanitize PDF content before it reaches users.
Valters IT
Securing Digital Frontiers
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.