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

CVE-2026-72910: ERPNext Privilege Escalation Vulnerability

CVE-2026-72910 is a privilege escalation vulnerability in ERPNext that allows authenticated users to modify protected data beyond their assigned roles. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-72910 Overview

CVE-2026-72910 is a missing authorization vulnerability [CWE-862] in ERPNext, the open-source Enterprise Resource Planning application built on the Frappe framework. Versions prior to 15.112.0 and 16.22.0 expose several whitelisted server methods that skip write-permission checks. Authenticated users with limited roles can invoke merge_account, pause_job_for_doc, trigger_job_for_doc, change_release_date, and update_cost_center to modify accounting objects outside their assigned scope. The issue affects code paths in erpnext/accounts/doctype/account/account.py, process_payment_reconciliation.py, purchase_invoice.py, and erpnext/accounts/utils.py. Patched builds 15.112.0 and 16.22.0 add explicit check_permission("write") calls on the referenced documents.

Critical Impact

Any authenticated ERPNext user can tamper with GL accounts, cost centers, purchase invoice release dates, and payment reconciliation jobs, breaking financial integrity controls.

Affected Products

  • ERPNext versions prior to 15.112.0 (v15 branch)
  • ERPNext versions prior to 16.22.0 (v16 branch)
  • Frappe/ERPNext deployments exposing whitelisted RPC endpoints to authenticated users

Discovery Timeline

  • 2026-08-10 - CVE-2026-72910 published to NVD
  • 2026-08-11 - Last updated in NVD database

Technical Details for CVE-2026-72910

Vulnerability Analysis

ERPNext exposes Python functions to authenticated HTTP callers using the @frappe.whitelist() decorator. Whitelisting alone only confirms that a signed-in session may call the method. It does not verify that the caller holds the DocType-level write permission required for the underlying record. The affected functions load target documents through frappe.get_cached_doc and then mutate accounting state directly.

Because check_permission was omitted, a user with a low-privilege role such as Accounts User, Employee, or a custom limited role could call the endpoints and alter records controlled by Accounts Manager or System Manager. The affected operations include merging GL accounts, pausing or triggering scheduled reconciliation jobs, editing purchase invoice release dates, and updating cost centers linked to transactions.

Root Cause

The root cause is a missing authorization check [CWE-862] on server-side write operations. Whitelisted callable methods trusted the decorator as a sufficient gate and never invoked the document-level permission API before mutating persistent data.

Attack Vector

Exploitation requires an authenticated ERPNext session with any valid role. The attacker issues an HTTP POST to /api/method/erpnext.accounts.doctype.account.account.merge_account (or one of the other affected methods) with parameters referencing target records. The server executes the mutation without validating the session's write access to those records.

python
# Patch: erpnext/accounts/doctype/account/account.py
 @frappe.whitelist()
 def merge_account(old, new):
 	_ensure_idle_system()
-	# Validate properties before merging
 	new_account = frappe.get_cached_doc("Account", new)
 	old_account = frappe.get_cached_doc("Account", old)
 
+	new_account.check_permission("write")
+	old_account.check_permission("write")
+
 	if not new_account:
 		throw(_("Account {0} does not exist").format(new))
# Source: https://github.com/frappe/erpnext/commit/ba936eefabb784805daa4c602b4baec9fc243ff8

A second hardening change in bisect_accounting_statements.py restricts the build_tree method to POST requests only, preventing CSRF-style GET invocation:

python
# Patch: erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py
 				cur_node.save()
 
-	@frappe.whitelist()
+	@frappe.whitelist(methods=["POST"])
 	def build_tree(self):
 		frappe.db.delete("Bisect Nodes")
# Source: https://github.com/frappe/erpnext/commit/ba936eefabb784805daa4c602b4baec9fc243ff8

Detection Methods for CVE-2026-72910

Indicators of Compromise

  • HTTP requests to /api/method/erpnext.accounts.doctype.account.account.merge_account originating from users lacking Accounts Manager or System Manager roles.
  • Frappe audit-log entries showing Account, Cost Center, or Purchase Invoice mutations authored by non-privileged users.
  • Unexpected invocations of pause_job_for_doc, trigger_job_for_doc, change_release_date, or update_cost_center in application logs.
  • Financial records showing chart-of-accounts merges or release-date edits without a matching approval workflow entry.

Detection Strategies

  • Ingest Frappe/ERPNext application and Nginx access logs into a SIEM and alert on the affected /api/method/... paths correlated with user role.
  • Query the tabVersion table for changes to Account, Cost Center, and Purchase Invoice documents where the modifying user's role profile lacks write permission.
  • Baseline the frequency of merge_account and reconciliation-job triggers; alert on statistical anomalies.

Monitoring Recommendations

  • Enable Frappe's built-in Activity Log and forward it to centralized logging for retention beyond the default window.
  • Track authentication and session metadata alongside RPC calls to attribute mutations to specific users and IPs.
  • Review the GitHub Security Advisory GHSA-qpvh-75wh-j645 for the authoritative list of vulnerable endpoints to watch.

How to Mitigate CVE-2026-72910

Immediate Actions Required

  • Upgrade ERPNext to 15.112.0 (v15 branch) or 16.22.0 (v16 branch) using bench update or your deployment pipeline.
  • Audit historical changes to Account, Cost Center, and Purchase Invoice records for unauthorized modifications since deployment.
  • Review role assignments and remove unnecessary privileges from user accounts that do not require accounting write access.

Patch Information

The vendor released fixes in ERPNext v15.112.0 and ERPNext v16.22.0. The changes are consolidated in Pull Request #55709 and backport commits ba936ee, 2ae6451, and 8c7a313a. The patches add check_permission("write") calls before mutating documents and restrict build_tree to POST.

Workarounds

  • If patching is delayed, restrict network access to the ERPNext /api/method/ endpoints to trusted operator IPs via reverse-proxy allowlists.
  • Reduce blast radius by tightening DocType Permissions for non-administrator roles until the upgrade is applied.
  • Monitor for calls to the affected whitelisted functions and disable accounts that invoke them without authorization.
bash
# Upgrade ERPNext using bench
bench get-app --branch version-15 erpnext
bench update --reset
bench --site your-site.local migrate

# Verify installed version
bench version | grep erpnext
# Expected: erpnext 15.112.0 (or 16.22.0)

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.