{"id":49354,"date":"2026-10-15T16:45:16","date_gmt":"2026-10-15T11:15:16","guid":{"rendered":"https:\/\/www.getastra.com\/blog\/?p=49354"},"modified":"2026-10-21T15:16:08","modified_gmt":"2026-10-21T09:46:08","slug":"cve-2026-94244","status":"publish","type":"post","link":"https:\/\/www.getastra.com\/blog\/vulnerability\/cve-2026-94244\/","title":{"rendered":"CVE-2026-94244: Missing Authorization in Wallet System for WooCommerce"},"content":{"rendered":"<div class=\"gb-container gb-container-83f53fef\">\n\n<p class=\"wp-block-paragraph\"><strong>Product Name:<\/strong> Wallet System in WooCommerce<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Vulnerability:<\/strong> Missing Authorization Leading to Store-Wide Customer Data Exposure via Exported Wallet Transaction File<br><br><strong>Vulnerable Version:<\/strong> &lt; 2.8.0<br><br><strong>Patched Version:<\/strong> 2.8.0<br><br><strong>CVE:<\/strong> CVE-2026-94244<br><br><strong>CVSS:<\/strong> 4.3 (Medium)&nbsp; AV:N\/AC:L\/PR:L\/UI:N\/S:U\/C:L\/I:N\/A:N<br><br><strong>CWE:<\/strong> CWE-862 (Missing Authorization) \u2192 CWE-200 (Sensitive Information Disclosure)<\/p>\n\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On 02\/09\/2026, a security researcher at Astra Security found a Missing Authorization vulnerability in <a href=\"https:\/\/wpscan.com\/vulnerability\/991f28f3-9cd8-4918-8431-a063eb2ba536\/\" target=\"_blank\" rel=\"noopener\">Wallet System for WooCommerce<\/a>, a popular WordPress plugin by WP Swings that adds wallet-based payments to WooCommerce stores.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The root cause is a Missing Authorization vulnerability (CWE-862) leading to Sensitive Information Disclosure via Exported File (CWE-200) in the plugin\u2019s administrative wallet-transaction export feature. The feature itself is a legitimate bookkeeping tool, letting store administrators export every customer\u2019s wallet-transaction history as a PDF or CSV file. The problem is who\u2019s allowed to trigger it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In its current form, any authenticated user with Subscriber-level access or higher can POST a nonce sourced from an unrelated feature to any <code>\/wp-admin\/*.php <\/code>URL and receive back a full database dump of every customer\u2019s wallet transactions and PII. On a WooCommerce store, this includes every Customer-tier account.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The flaw sits in the export handler\u2019s registration and authorization logic within <code>admin\/class-wallet-system-for-woocommerce-admin.php<\/code>, specifically in <code>wps_wsfw_download_pdf_file_callback()<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Technical_Breakdown_of_CVE-2026-94244\"><\/span>Technical Breakdown of CVE-2026-94244<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>CVE-2026-94244<\/strong> was discovered during a manual security review of the plugin\u2019s administrative export functionality and global hook registrations. The vulnerability is a textbook combination of two WordPress-specific missteps compounded in one function.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The export handler is registered on WordPress\u2019s global init hook and gated by nothing more than an <code>is_admin() wrapper<\/code>, which checks only whether the request URL falls under<code> \/wp-admin\/<\/code>, not whether the requester holds any actual permission to be there. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The handler itself performs no login check and no capability check. Its single real gate is a <code>wp_verify_nonce()<\/code> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_was_CVE-2026-94244_discovered\"><\/span>How was CVE-2026-94244 discovered?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1306\" height=\"467\" src=\"\/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/cdn-blog.getastra.com\/2026\/10\/581265e4-image.png\" alt=\"CVE-2026-94244\" class=\"wp-image-49355\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">While reviewing the plugin\u2019s admin hook registrations in <code>includes\/class-wallet-system-for-woocommerce.php<\/code>, our researcher noticed the export function hooked directly onto WordPress\u2019s global init action, with no capability check and only a generic nonce as a gate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php\n\n$this-&gt;loader-&gt;add_action(\n\n&nbsp;&nbsp;&nbsp;&nbsp;'init',\n\n&nbsp;&nbsp;&nbsp;&nbsp;$wsfw_plugin_admin,\n\n&nbsp;&nbsp;&nbsp;&nbsp;'wps_wsfw_download_pdf_file_callback'\n\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Pulling the handler itself <code>(admin\/class-wallet-system-for-woocommerce-admin.php)<\/code>, the researcher found a <code>single wp_verify_nonce() <\/code>call standing between any authenticated user and a store-wide database export:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php\n\npublic function wps_wsfw_download_pdf_file_callback() {\n\n&nbsp;&nbsp;&nbsp;&nbsp;$nonce = ( isset( $_POST&#91;'updatenoncewallet_pdf_dwnload'] ) )\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;? sanitize_text_field( wp_unslash( $_POST&#91;'updatenoncewallet_pdf_dwnload'] ) )\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: '';\n\n&nbsp;&nbsp;&nbsp;&nbsp;if ( wp_verify_nonce( $nonce ) ) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ ^-- THE ENTIRE GATE. No login check. No capability check. Default action (-1).\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( isset( $_POST&#91;'wps_wsfw_export_pdf'] ) ) {\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;global $wpdb;\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$transactions = $wpdb-&gt;get_results(\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'SELECT * FROM ' . $wpdb-&gt;prefix . 'wps_wsfw_wallet_transaction ORDER BY Id DESC'\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ ^-- every row, every user, no WHERE clause\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\n\n&nbsp;&nbsp;&nbsp;&nbsp;}\n\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Two things stood out immediately. First, the SQL query carried no <code>WHERE user_id = \u2026 clause<\/code>, 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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To confirm the vulnerability was exploitable from a low-privileged account, the researcher logged in as a plain Customer and loaded the plugin\u2019s own front-end \u201cMy Account \u2192 Wallet\u201d page. That page unconditionally renders a second hidden form field carrying a bare default-action nonce for a completely unrelated feature:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php\n\n&lt;input type=\"hidden\" id=\"wps_verifynonce\" name=\"wps_verifynonce\"\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value=\"&lt;?php echo esc_attr( wp_create_nonce() ); ?&gt;\" \/&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Taking that nonce and replaying it against \/wp-admin\/admin.php with wps_wsfw_export_pdf=1 returned a genuine PDF containing another user\u2019s seeded wallet transactions. This confirmed the Missing Authorization vulnerability (CWE-862), leading to the responsible disclosure and this advisory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_to_replicate_the_vulnerability_CVE-2026-94244\"><\/span>How to replicate the vulnerability CVE-2026-94244<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Prerequisites<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A running instance of Wallet System for <strong>WooCommerce &lt; 2.8.0<\/strong> installed on <strong>WordPress 6.9.4 + WooCommerce 11.0.1 <\/strong>(versions used by the researcher).<\/li>\n\n\n\n<li>Two WooCommerce Customer accounts: \u201c<strong>victim<\/strong>\u201d (with seeded wallet transactions) and \u201cattacker\u201d (with no relationship to victim and no wallet-management privileges).<\/li>\n\n\n\n<li>Network access to the WordPress site.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Steps<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Seed the \u201cvictim\u201d Customer account with wallet transaction history. In the researcher\u2019s test, two transactions were used: a $250 PayPal Wallet Recharge and a $40 Order Payment, both tied to victim@example.com.<\/li>\n\n\n\n<li>Log in to the WordPress site as the \u201cattacker\u201d Customer account and confirm the attacker cannot load the plugin\u2019s admin wallet dashboard directly (as expected, given that dashboard\u2019s own manage_options gate).<\/li>\n\n\n\n<li>From the attacker\u2019s session, load the front-end \u201cMy Account \u2192 Wallet\u201d 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.<\/li>\n\n\n\n<li>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\u2019s authenticated session cookies:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>http\n\nPOST \/wp-admin\/admin.php HTTP\/1.1\n\nCookie: &lt;attacker's own authenticated session&gt;\n\nContent-Type: application\/x-www-form-urlencoded\n\nupdatenoncewallet_pdf_dwnload=&lt;attacker's own nonce&gt;&amp;wps_wsfw_export_pdf=1<\/code><\/pre>\n\n\n\n<ol start=\"5\" class=\"wp-block-list\">\n<li>The server responds with HTTP 200 OK, <code>Content-Type: application\/pdf<\/code>, and <code>Content-Disposition: attachment; filename=\"transaction.pdf<\/code>&#8220;.<\/li>\n\n\n\n<li>Decompressing and inspecting the returned PDF\u2019s content stream confirms it contains the victim\u2019s real transaction history, including the <strong>$40 <\/strong>Order Payment and <strong>$250<\/strong> PayPal Wallet Recharge rows, correctly attributed to victim@example.com:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>-- decompressed PDF content stream (excerpt) --\n\nvictim | victim@example.com | Customer | $40.00 | Order Payment | Wallet\n\nvictim | victim@example.com | Customer | $250.00 | Wallet Recharge | PayPal<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Alternative payload (CSV export):<\/strong> Replace <code>wps_wsfw_export_pdf=1<\/code> with <code>wps_wsfw_export_csv=1<\/code> to receive the same data as a CSV file instead of a PDF.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Impact of CVE-2026-94244<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Any authenticated Subscriber-tier (or higher) account can obtain a complete, store-wide export of every customer\u2019s wallet transaction history and personally identifiable information in a single request. The vulnerability could lead to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Full export of every customer\u2019s PII across the entire store (name, email address, role)<\/li>\n\n\n\n<li>Full export of every customer\u2019s financial transaction history (amounts, payment methods, transaction types, IDs, dates)<\/li>\n\n\n\n<li>Breach of financial confidentiality obligations under<strong> GDPR<\/strong>, <strong>PCI DSS<\/strong>, and similar regimes<\/li>\n\n\n\n<li>Secondary targeting of individual high-value customers using the exfiltrated data<\/li>\n\n\n\n<li>Reconnaissance for follow-on attacks against the merchant\u2019s wider customer base<\/li>\n\n\n\n<li>Potential expansion to unauthenticated exploitation on deployments where a default-action nonce is reachable by guest visitors<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Current Status of CVE-2026-94244<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What Can You Do?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">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:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add a capability check (e.g., <code>current_user_can( 'manage_woocommerce'<\/code> ) or <code>current_user_can( 'manage_options' )<\/code>) 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., <code>wps_wsfw_current_user_can_manage_wallet()<\/code>).<\/li>\n\n\n\n<li>Replace the generic <code>wp_verify_nonce( $nonce ) <\/code>call with a feature-specific action string (e.g., <code>wp_verify_nonce( $nonce, 'wps_wsfw_export_transactions' )),<\/code> so the nonce can never be satisfied by an unrelated feature\u2019s token.<\/li>\n\n\n\n<li>As a defense-in-depth measure, audit all other init-registered handlers in the plugin for the same <code>is_admin()<\/code>-only gate pattern.<\/li>\n\n\n\n<li>Review web server access logs for POST requests to<code> \/wp-admin\/*.php<\/code> URLs carrying <code>wps_wsfw_export_pdf or wps_wsfw_export_csv<\/code> parameters from low-privileged user sessions.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.getastra.com\/services\/penetration-testing\">Astra Security<\/a> helps you test for this vulnerability and similar missing-authorization flaws during a manual pentest.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Product Name: Wallet System in WooCommerce Vulnerability: Missing Authorization Leading to Store-Wide Customer Data Exposure via Exported Wallet Transaction File Vulnerable Version: &lt; 2.8.0 Patched Version: 2.8.0 CVE: CVE-2026-94244 CVSS: 4.3 (Medium)&nbsp; AV:N\/AC:L\/PR:L\/UI:N\/S:U\/C:L\/I:N\/A:N CWE: CWE-862 (Missing Authorization) \u2192 CWE-200 (Sensitive Information Disclosure) On 02\/09\/2026, a security researcher at Astra Security found a Missing Authorization vulnerability &#8230; <a title=\"CVE-2026-94244: Missing Authorization in Wallet System for WooCommerce\" class=\"read-more\" href=\"https:\/\/www.getastra.com\/blog\/vulnerability\/cve-2026-94244\/\" aria-label=\"Read more about CVE-2026-94244: Missing Authorization in Wallet System for WooCommerce\">Read more<\/a><\/p>\n","protected":false},"author":138,"featured_media":49356,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[723],"tags":[],"class_list":["post-49354","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49354","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/users\/138"}],"replies":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/comments?post=49354"}],"version-history":[{"count":3,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49354\/revisions"}],"predecessor-version":[{"id":49472,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49354\/revisions\/49472"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/media\/49356"}],"wp:attachment":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/media?parent=49354"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/categories?post=49354"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/tags?post=49354"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}