CVE-2026-12415 - Invoice Generator unauthenticated account takeover
The Invoice Generator plugin for WordPress through 1.0.0 exposes
pravel_invoice_edit_account() through wp_ajax_nopriv_pravel_invoice_edit_account.
The handler accepts attacker-controlled user_id and user_email values and
calls wp_update_user() without proving authentication, ownership, capability,
or nonce validity. An unauthenticated attacker can change an administrator’s
email address and then use the normal password-reset flow to take over the
account.
This is a server-side authorization failure in an AJAX account-management handler, not a password-reset weakness.
When to use it
Use this recipe when a repository deploys, vendors, forks, or maintains the Invoice Generator WordPress plugin or equivalent unauthenticated AJAX account mutation code. It is designed for source-code remediation, authentication and capability review, object-level ownership checks, account-takeover impact assessment, and evidence that unauthenticated callers cannot mutate user email addresses.
Inputs
- Plugin version, WordPress deployment inventory, plugin source/fork state, AJAX action registrations, authentication/capability policy, nonce strategy, and generated dependency or SBOM reports.
- Source paths that register
wp_ajax_nopriv_*, callwp_update_user, acceptuser_idoruser_email, handle password resets, or manage account profile updates. - Regression fixtures for unauthenticated denial, wrong-user denial, nonce failure, capability failure, owner success, admin success, and password-reset follow-up.
- Boundary evidence: admin/user accounts, plugin activation state, exposed sites, audit logs, password-reset logs, credential rotation owner, and rollout owner.
Affected versions
- Vulnerable: Invoice Generator plugin
<=1.0.0 - Fixed: no fixed version was listed in the advisory data at publication
- Affected surface: unauthenticated WordPress AJAX account edit action
Indicator-of-exposure
- The repository deploys, vendors, forks, or maintains the Invoice Generator
WordPress plugin at
<=1.0.0. - Code registers
wp_ajax_nopriv_pravel_invoice_edit_accountor a similar account edit action. - Request handlers pass
user_idoruser_emailfrom$_POSTintowp_update_user()without an authenticated capability check and nonce.
Quick checks:
rg -n "pravel_invoice_edit_account|wp_ajax_nopriv|wp_update_user|user_email|check_ajax_referer|current_user_can" .
wp plugin list | rg "invoice|creator|generator"
Windows:
rg -n "pravel_invoice_edit_account|wp_ajax_nopriv|wp_update_user|user_email|check_ajax_referer|current_user_can" .
wp plugin list | rg "invoice|creator|generator"
Remediation strategy
- Remove or disable the affected plugin until a trusted fixed release is available.
- If this repository owns the plugin code, remove the
noprivregistration for account mutation and require authentication before touching user records. - Require
check_ajax_referer(),current_user_can()for the exact account management action, and object-level ownership checks. - Do not allow client-supplied
user_idto select arbitrary accounts for email changes. - Review administrator email changes and password-reset events during the exposure window.
The prompt
Model context: this prompt was generated by GPT 5.5 Extra High reasoning.
You are remediating CVE-2026-12415 / GHSA-f3q2-677p-c93v in the WordPress
Invoice Generator plugin. An unauthenticated AJAX action can change any user's
email and enable account takeover through password reset. Produce exactly one
output:
- A reviewer-ready PR/change request that disables or patches the plugin,
removes unauthenticated account mutation, adds authorization tests, and
documents operator cleanup, or
- TRIAGE.md if this repository does not control an affected WordPress runtime
or plugin fork.
## Rules
- Scope only CVE-2026-12415 and directly related account-edit AJAX handlers.
- Treat user IDs, emails, password-reset tokens, administrator accounts, and
audit logs as sensitive.
- Do not change real administrator emails or trigger live password resets for
validation.
- Do not leave a `wp_ajax_nopriv_*` route able to mutate user records.
- Do not auto-merge.
## Steps
1. Inventory every WordPress deployment, plugin folder, composer package,
container image, and vendor copy controlled by this repository.
2. Confirm whether Invoice Generator `<=1.0.0` or a forked copy of the affected
AJAX handler is present.
3. Search all AJAX account-management handlers for unauthenticated registration,
missing nonces, missing capability checks, and client-controlled account IDs.
4. If this repository does not control an affected runtime or plugin fork, stop
with `TRIAGE.md` naming the runtime owner and required action: disable the
plugin until a fixed release is available.
5. Remove or disable the affected plugin, or patch the handler if this
repository owns the code.
6. For owned code, remove the `wp_ajax_nopriv_pravel_invoice_edit_account`
registration and require authenticated access.
7. Add server-side authorization:
- validate a nonce with `check_ajax_referer()`;
- require a precise `current_user_can()` capability;
- verify the caller may edit the target account;
- ignore or reject arbitrary client-supplied `user_id` for self-service
account changes.
8. Add regression tests or static checks proving unauthenticated requests cannot
update any user's email and low-privilege users cannot update administrators.
9. Add a PR body section named `CVE-2026-12415 operator actions` covering:
- plugin versions before and after;
- whether the plugin was disabled or patched;
- administrator email and password-reset log review;
- user/session invalidation or credential reset guidance;
- validation that passed.
10. Run available validation: PHP lint, WordPress plugin tests, static scans,
deployment render, and dependency/security scans.
11. Use PR title:
`fix(sec): block Invoice Generator account takeover`.
## Stop conditions
- No affected WordPress plugin or fork is controlled by this repository.
- A fixed upstream release is unavailable and product owners must approve
disabling or replacing the plugin.
- Validation would require changing real administrator account state.
- Validation fails for unrelated pre-existing reasons; document those failures.
Output contract
- A reviewer-ready PR or change request that disables or patches the plugin, removes unauthenticated account mutation, adds nonce/capability/ownership checks, and documents account review.
- Or a
TRIAGE.mdfile that lists inspected plugin/deployment files, owner, observed version, AJAX account-mutation boundary, required fix, and residual risk. - The output must include exact validation commands and must not change real user emails, trigger production password resets, expose account data, or weaken WordPress capability checks.
Verification - what the reviewer looks for
- No unauthenticated AJAX route can mutate WordPress user records.
- Email changes require authentication, nonce validation, capability checks, and object-level authorization.
- Admin email and password-reset logs are reviewed if exposure existed.
Watch for
- Removing the UI action while leaving the
wp_ajax_nopriv_*registration. - Checking only authentication but not whether the caller can edit the target user.
- Allowing self-service profile updates to accept arbitrary
user_idvalues.
Related recipes
- Source code authz tenant boundary audit
- Source code injection sink audit
- OWASP Top 10 2026 audit
- SAST finding triage and fix
References
- GitHub Advisory: https://github.com/advisories/GHSA-f3q2-677p-c93v
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-12415
- Wordfence advisory: https://www.wordfence.com/threat-intel/vulnerabilities/id/ee045d0d-101a-4ae2-b209-4a4865eec195?source=cve
- Source reference: https://plugins.trac.wordpress.org/browser/invoice-creator/trunk/lib/user-manage-function.php