CVE-2026-9021: Easy Invoice (WP): missing authz on quote accept/decline

MEDIUM
Published July 9, 2026
CISO Take

The Easy Invoice WordPress plugin (up to 2.1.19) exposes its quote accept/decline AJAX actions to unauthenticated visitors, and the only real protection — a per-quote nonce — is rendered directly into the public quote page, so anyone who loads that page can harvest it and act on the quote. This is not an AI/ML vulnerability despite the ai_agent tag in our pipeline: it's a standard WordPress business-logic auth bypass in an invoicing plugin, and it belongs on your radar only if this plugin runs on a customer-facing WordPress site. The severity is genuinely low (CVSS 5.3, confidentiality and availability both unaffected, only integrity of a quote record) and EPSS sits at 0.3% — top 78th percentile relative to other CVEs, but still a low absolute exploitation likelihood — with no CISA KEV listing, no public exploit, and no Nuclei template observed. Patch to the fixed release referenced in the WordPress.org changeset (2.2.0) when convenient, and if you run the Pro tier, enable `easy_invoice_pro_restrict_quote_to_client` as a compensating control in the meantime; this is routine patch-cycle hygiene, not an incident.

Sources: NVD EPSS wordfence.com plugins.trac.wordpress.org

What is the risk?

Low real-world risk: exploitability is trivial (no auth, no user interaction, nonce is exposed by design) but impact is narrow — an attacker can only flip the state of a quote (accept/decline/auto-convert to invoice) that is already publicly viewable, with no confidentiality or availability impact per the CVSS vector (C:N/I:L/A:N). EPSS (0.297%, ~78th percentile) and absence from CISA KEV both indicate this is not being actively exploited or prioritized by opportunistic scanners today. This is flagged in our pipeline as ai_agent, but nothing in the CVE description, affected code, or references involves an AI/ML component — treat the AI tag as a classification artifact, not a signal of AI-specific risk.

How does the attack unfold?

Reconnaissance
Attacker loads the publicly accessible single quote page and extracts the quote-scoped nonce embedded in the template HTML.
Exploitation
Attacker submits a forged AJAX request to admin-ajax.php with the harvested nonce and the easy_invoice_accept_quote or easy_invoice_decline_quote action, bypassing the ownership check that is disabled by default.
Impact
The targeted quote is accepted or declined without authorization, and depending on configuration is auto-converted to an invoice and emailed to the client, causing unauthorized business-record manipulation.

What systems are affected?

Package Ecosystem Vulnerable Range Patched
Easy Invoice – Invoice Generator, PDF Quotes & Payments No patch

Do you use Easy Invoice – Invoice Generator, PDF Quotes & Payments? You're affected.

How severe is it?

CVSS 3.1
5.3 / 10
EPSS
0.3%
chance of exploitation in 30 days
Higher than 22% of all CVEs
Exploitation Status
No known exploitation
Sophistication
Trivial

What is the attack surface?

AV AC PR UI S C I A
AV Network
AC Low
PR None
UI None
S Unchanged
C None
I Low
A None

What should I do?

1 step
  1. 1) Update Easy Invoice to the patched release (fix landed in the 2.2.0 changeset referenced by WordPress.org, commit 3517910). 2) If running Easy Invoice Pro, enable the easy_invoice_pro_restrict_quote_to_client option immediately as a compensating control — it is off by default and directly closes the ownership-check gap. 3) Monitor admin-ajax.php access logs for unauthenticated POST requests with action=easy_invoice_accept_quote or action=easy_invoice_decline_quote originating outside expected client sessions. 4) Audit recently converted invoices for quotes that were accepted/declined without a corresponding client-side session or login.

What does CISA's SSVC say?

Decision Track
Exploitation none
Automatable No
Technical Impact partial

Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.

How is it classified?

Auth Bypass Plugin

Which compliance frameworks are affected?

Compliance analysis pending. Sign in for full compliance mapping when available.

Frequently Asked Questions

What is CVE-2026-9021?

The Easy Invoice WordPress plugin (up to 2.1.19) exposes its quote accept/decline AJAX actions to unauthenticated visitors, and the only real protection — a per-quote nonce — is rendered directly into the public quote page, so anyone who loads that page can harvest it and act on the quote. This is not an AI/ML vulnerability despite the ai_agent tag in our pipeline: it's a standard WordPress business-logic auth bypass in an invoicing plugin, and it belongs on your radar only if this plugin runs on a customer-facing WordPress site. The severity is genuinely low (CVSS 5.3, confidentiality and availability both unaffected, only integrity of a quote record) and EPSS sits at 0.3% — top 78th percentile relative to other CVEs, but still a low absolute exploitation likelihood — with no CISA KEV listing, no public exploit, and no Nuclei template observed. Patch to the fixed release referenced in the WordPress.org changeset (2.2.0) when convenient, and if you run the Pro tier, enable `easy_invoice_pro_restrict_quote_to_client` as a compensating control in the meantime; this is routine patch-cycle hygiene, not an incident.

Is CVE-2026-9021 actively exploited?

No confirmed active exploitation of CVE-2026-9021 has been reported, but organizations should still patch proactively.

How to fix CVE-2026-9021?

1) Update Easy Invoice to the patched release (fix landed in the 2.2.0 changeset referenced by WordPress.org, commit 3517910). 2) If running Easy Invoice Pro, enable the `easy_invoice_pro_restrict_quote_to_client` option immediately as a compensating control — it is off by default and directly closes the ownership-check gap. 3) Monitor `admin-ajax.php` access logs for unauthenticated POST requests with `action=easy_invoice_accept_quote` or `action=easy_invoice_decline_quote` originating outside expected client sessions. 4) Audit recently converted invoices for quotes that were accepted/declined without a corresponding client-side session or login.

What is the CVSS score for CVE-2026-9021?

CVE-2026-9021 has a CVSS v3.1 base score of 5.3 (MEDIUM). The EPSS exploitation probability is 0.30%.

What are the technical details?

Original Advisory

The Easy Invoice plugin for WordPress is vulnerable to Missing Authorization in versions up to, and including, 2.1.19. This is due to the plugin registering the easy_invoice_accept_quote and easy_invoice_decline_quote AJAX actions via wp_ajax_nopriv_ hooks and relying solely on a quote-scoped nonce that is rendered into the publicly accessible single quote template, combined with an ownership check that is gated behind an off-by-default Pro option (easy_invoice_pro_restrict_quote_to_client). This makes it possible for unauthenticated attackers to accept or decline arbitrary published quotes — and, depending on the configured accept action, automatically convert them into invoices (and even email them to the client) — by harvesting the per-quote nonce from the public quote page and submitting it to admin-ajax.

Exploitation Scenario

An unauthenticated attacker locates a public 'single quote' page (e.g., shared via a quote link) and views its HTML source, where the plugin has rendered the quote-scoped WordPress nonce in plaintext. The attacker copies that nonce and the quote ID, then sends a forged POST request directly to `wp-admin/admin-ajax.php` with `action=easy_invoice_accept_quote`, bypassing any UI. Because the ownership check is gated behind an off-by-default Pro setting, the request succeeds: the quote is accepted, auto-converted into an invoice, and — depending on configuration — emailed to the client, all without the legitimate client ever approving it. This could be used to manipulate a business's billing records or socially engineer a client via an unexpected invoice email, but does not grant broader system access or data exposure.

Weaknesses (CWE)

CWE-862 — Missing Authorization: The product does not perform an authorization check when an actor attempts to access a resource or perform an action.

  • [Architecture and Design] Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries. Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
  • [Architecture and Design] Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].

Source: MITRE CWE corpus.

CVSS Vector

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N

Timeline

Published
July 9, 2026
Last Modified
July 9, 2026
First Seen
July 9, 2026

Related Vulnerabilities