CVE-2026-94244: Missing Authorization in Wallet System for WooCommerce

Updated: October 21st, 2026
8 mins read

Product Name: Wallet System in WooCommerce

Vulnerability: Missing Authorization Leading to Store-Wide Customer Data Exposure via Exported Wallet Transaction File

Vulnerable Version: < 2.8.0

Patched Version: 2.8.0

CVE: CVE-2026-94244

CVSS: 4.3 (Medium)  AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N

CWE: CWE-862 (Missing Authorization) → CWE-200 (Sensitive Information Disclosure)

On 02/09/2026, a security researcher at Astra Security found a Missing Authorization vulnerability in Wallet System for WooCommerce, a popular WordPress plugin by WP Swings that adds wallet-based payments to WooCommerce stores.

The root cause is a Missing Authorization vulnerability (CWE-862) leading to Sensitive Information Disclosure via Exported File (CWE-200) in the plugin’s administrative wallet-transaction export feature. The feature itself is a legitimate bookkeeping tool, letting store administrators export every customer’s wallet-transaction history as a PDF or CSV file. The problem is who’s allowed to trigger it.

In its current form, any authenticated user with Subscriber-level access or higher can POST a nonce sourced from an unrelated feature to any /wp-admin/*.php URL and receive back a full database dump of every customer’s wallet transactions and PII. On a WooCommerce store, this includes every Customer-tier account.

The flaw sits in the export handler’s registration and authorization logic within admin/class-wallet-system-for-woocommerce-admin.php, specifically in wps_wsfw_download_pdf_file_callback().

Technical Breakdown of CVE-2026-94244

CVE-2026-94244 was discovered during a manual security review of the plugin’s administrative export functionality and global hook registrations. The vulnerability is a textbook combination of two WordPress-specific missteps compounded in one function.

The export handler is registered on WordPress’s global init hook and gated by nothing more than an is_admin() wrapper, which checks only whether the request URL falls under /wp-admin/, not whether the requester holds any actual permission to be there.

The handler itself performs no login check and no capability check. Its single real gate is a wp_verify_nonce() call invoked with no action argument, which WordPress silently defaults to the catch-all generic nonce action, meaning any default-action nonce already minted anywhere else on the site for the same logged-in user will satisfy it.

How was CVE-2026-94244 discovered?

CVE-2026-94244

While reviewing the plugin’s admin hook registrations in includes/class-wallet-system-for-woocommerce.php, our researcher noticed the export function hooked directly onto WordPress’s global init action, with no capability check and only a generic nonce as a gate:

php

$this->loader->add_action(

    'init',

    $wsfw_plugin_admin,

    'wps_wsfw_download_pdf_file_callback'

);

Pulling the handler itself (admin/class-wallet-system-for-woocommerce-admin.php), the researcher found a single wp_verify_nonce() call standing between any authenticated user and a store-wide database export:

php

public function wps_wsfw_download_pdf_file_callback() {

    $nonce = ( isset( $_POST['updatenoncewallet_pdf_dwnload'] ) )

        ? sanitize_text_field( wp_unslash( $_POST['updatenoncewallet_pdf_dwnload'] ) )

        : '';

    if ( wp_verify_nonce( $nonce ) ) {

        // ^-- THE ENTIRE GATE. No login check. No capability check. Default action (-1).

        if ( isset( $_POST['wps_wsfw_export_pdf'] ) ) {

            global $wpdb;

            $transactions = $wpdb->get_results(

                'SELECT * FROM ' . $wpdb->prefix . 'wps_wsfw_wallet_transaction ORDER BY Id DESC'

            );

            // ^-- every row, every user, no WHERE clause

        }

    }

}

Two things stood out immediately. First, the SQL query carried no WHERE user_id = … clause, so the export dumped the entire transactions table regardless of who requested it. Second, with the nonce check defaulting to the generic action, any nonce the attacker could get WordPress to mint for their own session would unlock the export.

To confirm the vulnerability was exploitable from a low-privileged account, the researcher logged in as a plain Customer and loaded the plugin’s own front-end “My Account → Wallet” page. That page unconditionally renders a second hidden form field carrying a bare default-action nonce for a completely unrelated feature:

php

<input type="hidden" id="wps_verifynonce" name="wps_verifynonce"

       value="<?php echo esc_attr( wp_create_nonce() ); ?>" />

Taking that nonce and replaying it against /wp-admin/admin.php with wps_wsfw_export_pdf=1 returned a genuine PDF containing another user’s seeded wallet transactions. This confirmed the Missing Authorization vulnerability (CWE-862), leading to the responsible disclosure and this advisory.

How to replicate the vulnerability CVE-2026-94244

Prerequisites

  • A running instance of Wallet System for WooCommerce < 2.8.0 installed on WordPress 6.9.4 + WooCommerce 11.0.1 (versions used by the researcher).
  • Two WooCommerce Customer accounts: “victim” (with seeded wallet transactions) and “attacker” (with no relationship to victim and no wallet-management privileges).
  • Network access to the WordPress site.

Steps

  1. Seed the “victim” Customer account with wallet transaction history. In the researcher’s test, two transactions were used: a $250 PayPal Wallet Recharge and a $40 Order Payment, both tied to [email protected].
  2. Log in to the WordPress site as the “attacker” Customer account and confirm the attacker cannot load the plugin’s admin wallet dashboard directly (as expected, given that dashboard’s own manage_options gate).
  3. From the attacker’s session, load the front-end “My Account → Wallet” page and extract the value of the hidden wps_verifynonce field. This nonce is minted using wp_create_nonce() with no action argument, giving the attacker a valid default-action nonce for their own session.
  4. POST that nonce to any /wp-admin/*.php URL (e.g., /wp-admin/admin.php), together with wps_wsfw_export_pdf=1, using the attacker’s authenticated session cookies:
http

POST /wp-admin/admin.php HTTP/1.1

Cookie: <attacker's own authenticated session>

Content-Type: application/x-www-form-urlencoded

updatenoncewallet_pdf_dwnload=<attacker's own nonce>&wps_wsfw_export_pdf=1
  1. The server responds with HTTP 200 OK, Content-Type: application/pdf, and Content-Disposition: attachment; filename="transaction.pdf“.
  2. Decompressing and inspecting the returned PDF’s content stream confirms it contains the victim’s real transaction history, including the $40 Order Payment and $250 PayPal Wallet Recharge rows, correctly attributed to [email protected]:
-- decompressed PDF content stream (excerpt) --

victim | [email protected] | Customer | $40.00 | Order Payment | Wallet

victim | [email protected] | Customer | $250.00 | Wallet Recharge | PayPal

Alternative payload (CSV export): Replace wps_wsfw_export_pdf=1 with wps_wsfw_export_csv=1 to receive the same data as a CSV file instead of a PDF.

Impact of CVE-2026-94244

Any authenticated Subscriber-tier (or higher) account can obtain a complete, store-wide export of every customer’s wallet transaction history and personally identifiable information in a single request. The vulnerability could lead to:

  • Full export of every customer’s PII across the entire store (name, email address, role)
  • Full export of every customer’s financial transaction history (amounts, payment methods, transaction types, IDs, dates)
  • Breach of financial confidentiality obligations under GDPR, PCI DSS, and similar regimes
  • Secondary targeting of individual high-value customers using the exfiltrated data
  • Reconnaissance for follow-on attacks against the merchant’s wider customer base
  • Potential expansion to unauthenticated exploitation on deployments where a default-action nonce is reachable by guest visitors

Current Status of CVE-2026-94244

The issue was responsibly disclosed to WP Swings through a coordinated disclosure channel and has been patched in version 2.8.0. The vulnerability was publicly catalogued by WPScan on 2026-10-06 (WPVDB ID 991f28f3-9cd8-4918-8431-a063eb2ba536), with the technical PoC embargoed until 2026-10-20 to give site owners time to update.

This finding is explicitly distinguished from CVE-2026-57332, a prior weak-nonce issue in the same plugin patched in versions 2.7.9 and 2.7.10. That earlier fix was scoped to wp_ajax_*-registered AJAX handlers in a different file. The vulnerable function described in this advisory is hooked on init in admin/class-wallet-system-for-woocommerce-admin.php and was not covered by that hardening pass. It was patched separately in 2.8.0.

What Can You Do?

Users should update Wallet System for WooCommerce to version 2.8.0 or later immediately. If an immediate update is not possible, implement the following workarounds:

  • Add a capability check (e.g., current_user_can( 'manage_woocommerce' ) or current_user_can( 'manage_options' )) before the nonce check in wps_wsfw_download_pdf_file_callback(), matching the pattern the vendor already uses correctly elsewhere in the plugin (e.g., wps_wsfw_current_user_can_manage_wallet()).
  • Replace the generic wp_verify_nonce( $nonce ) call with a feature-specific action string (e.g., wp_verify_nonce( $nonce, 'wps_wsfw_export_transactions' )), so the nonce can never be satisfied by an unrelated feature’s token.
  • As a defense-in-depth measure, audit all other init-registered handlers in the plugin for the same is_admin()-only gate pattern.
  • Review web server access logs for POST requests to /wp-admin/*.php URLs carrying wps_wsfw_export_pdf or wps_wsfw_export_csv parameters from low-privileged user sessions.

Astra Security helps you test for this vulnerability and similar missing-authorization flaws during a manual pentest.