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_*, call wp_update_user, accept user_id or user_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_account or a similar account edit action.
  • Request handlers pass user_id or user_email from $_POST into wp_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 nopriv registration 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_id to 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.md file 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_id values.

References