CVE-2026-57412

Gift Cards (Gift Vouchers and Packages) (WooCommerce Supported) <= 4.6.9 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
4.7.0
Patched in
7d
Time to patch

Description

The Gift Cards (Gift Vouchers and Packages) (WooCommerce Supported) plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.6.9. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.6.9
PublishedJuly 8, 2026
Last updatedJuly 14, 2026
Affected plugingift-voucher

What Changed in the Fix

Changes introduced in v4.7.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

nopriv_` for logged-out users. Since there is no `nopriv` registration, this is not an unauthenticated leak. So we are back to the AJAX handlers or shortcodes. The `wpgv_voucher_successful_shortcode` is definitely a "Missing Authorization" on an action (marking a voucher as paid). L…

Show full research plan

nopriv_for logged-out users. Since there is nonopriv` registration, this is not an unauthenticated leak.

So we are back to the AJAX handlers or shortcodes.
The `wpgv_voucher_successful_shortcode` is definitely a "Missing Authorization" on an action (marking a voucher as paid).
Let's focus on that as it's a very clear "Unauthorized Action".

One problem: How do we get a `voucheritem` ID?
If we can't create one via AJAX, we can just guess? They are sequential IDs.
Or we can use the "Check Voucher Balance" shortcode to find IDs?
`echo do_shortcode(' [wpgv-check-voucher-balance] ');`
Actually, let's stick to the AJAX voucher creation.

Final check on `wpgv_doajax_gift_card_pdf_save`:
The function `wpgv__doajax_gift_card_pdf_save_func` is definitely the target for the "Missing Authorization" on function.
The `nopriv` registration is inferred, but highly likely for a gift card plugin purchase flow.

1.  Create a "Success" page with `[wpgv-voucher-successful]`.
2.  Find/Create a "Gift Card" page with a form to get the nonce `wpgv_giftitems_form_verify`.
    *Note*:
Research Findings
Static analysis — not yet PoC-verified

Summary

The Gift Cards plugin for WordPress fails to implement proper authorization checks in its 'payment successful' shortcode and gift card saving AJAX handlers. This allows unauthenticated attackers to mark gift card orders as 'Paid' without completing payment or to create unauthorized voucher entries by manipulating request parameters within a one-hour window of order creation.

Vulnerable Code

// include/voucher-shortcodes.php line 8
function wpgv_voucher_successful_shortcode()
{
	global $wpdb;
	$return = '';

	$voucher_table 	= $wpdb->prefix . 'giftvouchers_list';
	// ... (omitted code)
	if (isset($_GET['voucheritem'])) {
		$voucheritem = absint($_GET['voucheritem']);
		$voucher_options = $wpdb->get_row(
			$wpdb->prepare("SELECT * FROM $voucher_table WHERE id = %d", $voucheritem)
		);
		$check_send_mail = $voucher_options->check_send_mail;

		if ((strtotime($voucher_options->voucheradd_time) + 3600) < strtotime(current_time('mysql'))) {
			return '<div class="error"><p>' . esc_html_e('This URL is invalid. You can not access this page directly.', 'gift-voucher') . '</p></div>';
		}

		// ... (omitted code)

			if ($voucherrow) {
				$wpdb->update(
					$voucher_table,
					array(
						'payment_status' 	=> 'Paid',
						'voucheradd_time'	=> current_time('mysql')
					),
					array('id' => $voucheritem),
					array(
						'%s'
					),
					array('%d')
				);

---

// include/wpgv_giftcard_pdf.php line 8
function wpgv__doajax_gift_card_pdf_save_func()
{

	// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
	if (! isset($_POST['nonce']) || ! ! wp_verify_nonce(wp_unslash($_POST['nonce']), 'wpgv_giftitems_form_verify')) {
		wp_send_json_error(array('message' => 'Invalid security token'));
		wp_die();
	}

	global $wpdb;
	$voucher_table 	= $wpdb->prefix . 'giftvouchers_list';
    // ... (processes input and performs $wpdb->insert without capability check)

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/gift-voucher/4.6.9/admin.php /home/deploy/wp-safety.org/data/plugin-versions/gift-voucher/4.7.0/admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/gift-voucher/4.6.9/admin.php	2026-03-24 03:43:22.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/gift-voucher/4.7.0/admin.php	2026-05-15 03:40:58.000000000 +0000
@@ -2,6 +2,80 @@
 
 if (!defined('ABSPATH')) exit;  // Exit if accessed directly
 
+if (!function_exists('wpgv_is_plugin_admin_screen')) {
+	/**
+	 * Check whether the current admin request belongs to this plugin's own screens.
+	 *
+	 * @param WP_Screen|null $screen Optional screen object.
+	 * @return bool
+	 */
+	function wpgv_is_plugin_admin_screen($screen = null)
+	{
+		if (!is_admin()) {
+			return false;
+		}
+
+		if (null === $screen && function_exists('get_current_screen')) {
+			$screen = get_current_screen();
+		}
+
+		$current_page = isset($_GET['page']) ? sanitize_key(wp_unslash($_GET['page'])) : '';
+		$current_post_type = isset($_GET['post_type']) ? sanitize_key(wp_unslash($_GET['post_type'])) : '';
+		$current_taxonomy = isset($_GET['taxonomy']) ? sanitize_key(wp_unslash($_GET['taxonomy'])) : '';
+
+		$allowed_pages = array(
+			'wpgv-gift-cards',
+			'voucher-templates',
+			'new-voucher-template',
+			'view-voucher-details',
+			'voucher-setting',
+			'vouchers-lists',
+		);
+		$allowed_post_types = array(
+			'voucher_template',
+			'wpgv_voucher_product',
+		);
+		$allowed_taxonomies = array(
+			'wpgv_voucher_category',
+			'category_voucher_template',
+		);
+
+		if ($current_page && in_array($current_page, $allowed_pages, true)) {
+			return true;
+		}
+
+		if ($current_post_type && in_array($current_post_type, $allowed_post_types, true)) {
+			return true;
+		}
+
+		if ($current_taxonomy && in_array($current_taxonomy, $allowed_taxonomies, true)) {
+			return true;
+		}
+
+		if (!$screen) {
+			return false;
+		}
+
+		if (!empty($screen->post_type) && in_array($screen->post_type, $allowed_post_types, true)) {
+			return true;
+		}
+
+		if (!empty($screen->taxonomy) && in_array($screen->taxonomy, $allowed_taxonomies, true)) {
+			return true;
+		}
+
+		if (!empty($screen->id)) {
+			foreach ($allowed_pages as $allowed_page) {
+				if (false !== strpos($screen->id, $allowed_page)) {
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+}
+

Exploit Outline

The exploit targets the missing authorization in the `wpgv_voucher_successful_shortcode` function. An attacker first identifies or generates a pending gift card order (voucher item ID). They then navigate to the page containing the `[wpgv-voucher-successful]` shortcode, appending the `voucheritem` parameter with the targeted ID (e.g., `?voucheritem=123`). As long as the request is made within 3600 seconds of the voucher's creation, the plugin will update the `payment_status` to 'Paid' in the database without verifying if the current user is an admin or the legitimate payer. This results in the gift card being activated and potentially sent to a recipient without actual financial transaction completion.

Check if your site is affected.

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