CVE-2026-65822 Overview
CVE-2026-65822 is a SQL injection vulnerability [CWE-89] in ERPNext, the open source Enterprise Resource Planning platform maintained by Frappe. The flaw resides in erpnext/selling/report/inactive_customers/inactive_customers.py, where the get_sales_details and get_last_sales_amt functions accept an unvalidated doctype filter and interpolate it directly into raw SQL statements. An authenticated user can manipulate the filter to extract sensitive data or alter query behavior. The issue affects ERPNext releases prior to 15.116.0 and 16.23.0.
Critical Impact
Authenticated attackers can inject arbitrary SQL through the Inactive Customers report, exposing confidential ERP data and enabling query manipulation across the ERPNext database.
Affected Products
- ERPNext versions prior to 15.116.0
- ERPNext versions prior to 16.23.0
- erpnext/selling/report/inactive_customers/inactive_customers.py module
Discovery Timeline
- 2026-08-17 - CVE-2026-65822 published to NVD
- 2026-08-18 - Last updated in NVD database
Technical Details for CVE-2026-65822
Vulnerability Analysis
The Inactive Customers report in ERPNext generates sales activity summaries for customer records. The report handler accepts a doctype parameter that identifies whether to query Sales Order or Sales Invoice data. Prior to the patch, this parameter flowed directly into raw SQL strings without validation or parameterization.
Because the injected value is concatenated into the query body rather than bound as a parameter, an authenticated attacker with access to the report can substitute the expected doctype with crafted SQL. The result is classic in-band SQL injection against the ERPNext database backend.
The attack requires authentication but no user interaction. Successful exploitation allows extraction of arbitrary tables, including customer records, financial documents, and stored credentials referenced by ERPNext modules.
Root Cause
The root cause is improper neutralization of special elements in SQL commands [CWE-89]. The get_sales_details and get_last_sales_amt helpers built query strings using Python string interpolation with an untrusted doctype argument. No allowlist restricted the value to expected doctypes such as Sales Order or Sales Invoice, and the code did not use the Frappe Query Builder abstraction that provides safe parameter binding.
Attack Vector
An authenticated ERPNext user submits a request to the Inactive Customers report with a manipulated doctype filter. The malicious string is appended to the underlying SQL query, allowing UNION-based extraction, boolean-based inference, or destructive query manipulation depending on database permissions granted to the ERPNext service account.
# Patch excerpt from erpnext/selling/report/inactive_customers/inactive_customers.py
import frappe
from frappe import _
+from frappe.query_builder import Case, CustomFunction
+from frappe.query_builder.functions import Count, Max, Sum
from frappe.utils import cint
Source: GitHub commit 29dd6e6
The fix migrates the affected functions to the Frappe Query Builder (qb) and adds an allowlist that restricts the doctype filter to expected values, eliminating the raw string interpolation path.
Detection Methods for CVE-2026-65822
Indicators of Compromise
- Requests to the Inactive Customers report endpoint containing SQL metacharacters such as single quotes, UNION, SELECT, or comment sequences in the doctype parameter.
- ERPNext application logs showing database errors or malformed queries originating from inactive_customers.py.
- Unexpected read access patterns against tabSales Invoice, tabSales Order, or authentication-related tables from the ERPNext service account.
Detection Strategies
- Inspect HTTP request logs for doctype filter values that are not exactly Sales Order or Sales Invoice.
- Enable MariaDB or PostgreSQL query logging and alert on syntactically anomalous statements referencing the inactive customers report tables.
- Correlate authenticated ERPNext sessions with abnormal report execution volume, which can indicate automated injection probing.
Monitoring Recommendations
- Forward ERPNext application logs and database audit logs to a centralized SIEM for retention and correlation.
- Baseline normal report usage per user role and alert on deviations, particularly from low-privileged accounts accessing the Inactive Customers report.
- Monitor outbound traffic from the ERPNext host for signs of data exfiltration following report abuse.
How to Mitigate CVE-2026-65822
Immediate Actions Required
- Upgrade ERPNext to 15.116.0 or 16.23.0 or later, which contain the official fix.
- Audit ERPNext user accounts and restrict access to reporting features to roles that require them.
- Review database and application logs for signs of prior exploitation against the Inactive Customers report.
Patch Information
The fix is delivered in ERPNext v15.116.0 and v16.23.0. Technical remediation is tracked in pull request #55721 and commits 29dd6e6 and f43af66. See the GHSA-x35x-4mvx-h959 advisory for the coordinated disclosure record.
Workarounds
- Revoke access to the Inactive Customers report for non-administrative roles until the upgrade is applied.
- Deploy a web application firewall rule that blocks report requests containing SQL metacharacters in the doctype parameter.
- Restrict the ERPNext database service account to least-privilege permissions to limit the blast radius of any SQL injection.
# Upgrade ERPNext using the Frappe bench tool
bench update --patch
bench switch-to-branch version-15 erpnext --upgrade # or version-16
bench get-app erpnext --branch version-15
bench --site all migrate
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

