Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/simple-cloudflare-turnstile/inc/admin/admin-options.php
+++ b/simple-cloudflare-turnstile/inc/admin/admin-options.php
@@ -20,11 +20,14 @@
add_action('update_option_cfturnstile_key', 'cfturnstile_keys_updated', 10);
add_action('update_option_cfturnstile_secret', 'cfturnstile_keys_updated', 10);
function cfturnstile_keys_updated() {
- update_option('cfturnstile_tested', 'no');
+ update_option( 'cfturnstile_tested', 'no' );
+ delete_option( 'cfturnstile_invalid_secret_notice' );
+ delete_option( 'cfturnstile_soft_tested' );
+ delete_transient( 'cfturnstile_invalid_secret_throttle' );
}
// Admin test form to check Turnstile response
-function cfturnstile_admin_test() {
+function cfturnstile_admin_test( $soft = false ) {
?>
<form action="" method="POST" class="cfturnstile-settings">
<?php
@@ -34,19 +37,24 @@
$error = '';
if (isset($check['success'])) $success = $check['success'];
if (isset($check['error_code'])) $error = $check['error_code'];
- if ($success != true) {
+ if ( $success != true && ! $soft ) {
echo '<div style="padding: 20px 20px 25px 20px; margin: 20px 0 28px 0; background: #fff; border-radius: 20px; max-width: 500px; border: 2px solid #d5d5d5;">';
echo '<p style="font-weight: 600; font-size: 19px; margin-top: 0; margin-bottom: 0;">' . esc_html__('Almost done...', 'simple-cloudflare-turnstile') . '</p>';
}
- if (!isset($_POST['cf-turnstile-response'])) {
+ if ( ! isset($_POST['cf-turnstile-response']) ) {
+ if(! $soft ) {
echo '<p>'
. '<span style="color: red; font-weight: bold;">' . esc_html__('API keys have been updated. Please test the Turnstile API response below.', 'simple-cloudflare-turnstile') . '</span>'
. '<br/>'
. esc_html__('Turnstile will not be added to any forms until the test is successfully complete.', 'simple-cloudflare-turnstile')
. '</p>';
+ }
} else {
if ($success == true) {
- update_option('cfturnstile_tested', 'yes');
+ update_option( 'cfturnstile_tested', 'yes' );
+ delete_option( 'cfturnstile_invalid_secret_notice' );
+ delete_option( 'cfturnstile_soft_tested' );
+ delete_transient( 'cfturnstile_invalid_secret_throttle' );
} else {
if ($error == "missing-input-response") {
echo '<p style="font-weight: bold; color: red;">' . cfturnstile_failed_message() . '</p>';
@@ -65,7 +73,9 @@
echo '<button type="submit" style="margin-top: 10px; padding: 7px 10px; background: #1c781c; color: #fff; font-weight: bold; border: 1px solid #176017; border-radius: 4px; cursor: pointer;">
' . esc_html__('TEST RESPONSE', 'simple-cloudflare-turnstile') . ' <span class="dashicons dashicons-arrow-right-alt"></span>
</button>';
- echo '</div>';
+ if ( ! $soft ) {
+ echo '</div>';
+ }
}
}
?>
@@ -75,6 +85,7 @@
// Show Settings Page
function cfturnstile_settings_page() {
+
?>
<div class="sct-wrap wrap">
@@ -124,8 +135,21 @@
</div>
<?php
- if (empty(get_option('cfturnstile_tested')) || get_option('cfturnstile_tested') != 'yes') {
+ if ( empty( get_option( 'cfturnstile_tested' ) ) || get_option( 'cfturnstile_tested' ) != 'yes' ) {
echo cfturnstile_admin_test();
+ } elseif ( 'no' === get_option( 'cfturnstile_soft_tested' ) ) {
+ // Buffer the test form output so we can process the POST before deciding whether to show the wrapper.
+ ob_start();
+ cfturnstile_admin_test( true );
+ $soft_test_output = ob_get_clean();
+ // Re-check after processing — if the test passed, the flag will have been deleted.
+ if ( 'no' === get_option( 'cfturnstile_soft_tested' ) ) {
+ echo '<div style="padding: 20px 20px 25px 20px; margin: 20px 0 28px 0; background: #fff; border-radius: 20px; max-width: 500px; border: 2px solid #f0c33c;">';
+ echo '<p style="font-weight: 600; font-size: 19px; margin-top: 0; margin-bottom: 0;"><span class="dashicons dashicons-warning" style="color: #f0c33c; font-size: 28px; margin-right: 5px;"></span> ' . esc_html__( 'Re-test Recommended', 'simple-cloudflare-turnstile' ) . '</p>';
+ echo '<p>' . esc_html__( 'Cloudflare reported an invalid secret key error. Turnstile is still active on your forms, but verifications may be failing. Please re-test your API keys below.', 'simple-cloudflare-turnstile' ) . '</p>';
+ echo $soft_test_output;
+ echo '</div>';
+ }
}
?>
@@ -151,7 +175,7 @@
<?php
if ( !$cf_const_site && !$cf_const_secret ) {
- if (get_option('cfturnstile_tested') == 'yes') {
+ if ( get_option('cfturnstile_tested') == 'yes' && 'no' !== get_option( 'cfturnstile_soft_tested' ) ) {
echo '<p style=" font-weight: bold; color: #1e8c1e;"><span class="dashicons dashicons-yes-alt"></span> ' . esc_html__('Success! Turnstile is working correctly with your API keys.', 'simple-cloudflare-turnstile') . '</p>';
}
}
--- a/simple-cloudflare-turnstile/inc/errors.php
+++ b/simple-cloudflare-turnstile/inc/errors.php
@@ -27,6 +27,65 @@
}
/**
+ * Display persistent admin warning if an invalid secret key was detected.
+ * Dismissible via AJAX — stays until the admin clicks to dismiss.
+ */
+add_action( 'admin_notices', 'cfturnstile_invalid_secret_notice' );
+function cfturnstile_invalid_secret_notice() {
+ if ( '1' !== get_option( 'cfturnstile_invalid_secret_notice' ) ) {
+ return;
+ }
+ $settings_url = admin_url( 'options-general.php?page=cfturnstile' );
+ $ajax_url = esc_url( admin_url( 'admin-ajax.php' ) );
+ $nonce = wp_create_nonce( 'cfturnstile_dismiss_invalid_secret' );
+ ?>
+ <div class="notice notice-warning" id="cfturnstile-invalid-secret-notice">
+ <p>
+ <strong><?php esc_html_e( 'Cloudflare Turnstile:', 'simple-cloudflare-turnstile' ); ?></strong>
+ <?php
+ echo wp_kses_post(
+ sprintf(
+ /* translators: %s: URL to the plugin settings page. */
+ __( 'Your Turnstile secret key was rejected by Cloudflare (<code>invalid-input-secret</code>). Please verify your API keys on the <a href="%s">settings page</a>. Turnstile will continue to protect your forms, but verifications may fail until the key is corrected.', 'simple-cloudflare-turnstile' ),
+ esc_url( $settings_url )
+ )
+ );
+ ?>
+ </p>
+ <p>
+ <a href="#" id="cfturnstile-dismiss-invalid-secret" class="button button-small">
+ <?php esc_html_e( 'Dismiss', 'simple-cloudflare-turnstile' ); ?>
+ </a>
+ </p>
+ </div>
+ <script>
+ document.getElementById( 'cfturnstile-dismiss-invalid-secret' ).addEventListener( 'click', function( e ) {
+ e.preventDefault();
+ var notice = document.getElementById( 'cfturnstile-invalid-secret-notice' );
+ notice.style.display = 'none';
+ var xhr = new XMLHttpRequest();
+ xhr.open( 'POST', '<?php echo esc_url( $ajax_url ); ?>', true );
+ xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
+ xhr.send( 'action=cfturnstile_dismiss_invalid_secret&_wpnonce=<?php echo esc_attr( $nonce ); ?>' );
+ });
+ </script>
+ <?php
+}
+
+/**
+ * AJAX handler to dismiss the invalid secret notice.
+ */
+add_action( 'wp_ajax_cfturnstile_dismiss_invalid_secret', 'cfturnstile_dismiss_invalid_secret_handler' );
+function cfturnstile_dismiss_invalid_secret_handler() {
+ check_ajax_referer( 'cfturnstile_dismiss_invalid_secret', '_wpnonce' );
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_send_json_error( 'Unauthorized', 403 );
+ }
+ delete_option( 'cfturnstile_invalid_secret_notice' );
+ wp_send_json_success();
+}
+
+/**
* Gets the custom Turnstile failed message
*/
function cfturnstile_failed_message($default = "") {
--- a/simple-cloudflare-turnstile/inc/integrations/ecommerce/edd.php
+++ b/simple-cloudflare-turnstile/inc/integrations/ecommerce/edd.php
@@ -22,10 +22,9 @@
add_action('edd_purchase_form_before_submit', 'cfturnstile_field_edd_checkout', 10);
add_action('edd_pre_process_purchase', 'cfturnstile_edd_checkout_check');
function cfturnstile_edd_checkout_check() {
- if (!session_id()) { session_start(); }
- // Check if already validated
- if(isset($_SESSION['cfturnstile_edd_checkout_checked']) && wp_verify_nonce( sanitize_text_field($_SESSION['cfturnstile_edd_checkout_checked']), 'cfturnstile_edd_checkout' )) {
- unset($_SESSION['cfturnstile_edd_checkout_checked']);
+ // Check if already validated (cache-friendly, no PHP session)
+ if( cfturnstile_get_verified( 'cfturnstile_edd_checkout_checked' ) ) {
+ cfturnstile_clear_verified( 'cfturnstile_edd_checkout_checked' );
return;
}
// Get guest only
@@ -38,8 +37,7 @@
if($success != true) {
edd_set_error( 'cfturnstile_error', cfturnstile_failed_message() );
} else {
- $nonce = wp_create_nonce( 'cfturnstile_edd_checkout' );
- $_SESSION['cfturnstile_edd_checkout_checked'] = $nonce;
+ cfturnstile_set_verified( 'cfturnstile_edd_checkout_checked' );
}
}
}
--- a/simple-cloudflare-turnstile/inc/integrations/ecommerce/woocommerce.php
+++ b/simple-cloudflare-turnstile/inc/integrations/ecommerce/woocommerce.php
@@ -113,30 +113,28 @@
}
}
- // Start session
- if (!session_id()) { session_start(); }
- // Check if already validated
- if(isset($_SESSION['cfturnstile_checkout_checked']) && wp_verify_nonce( sanitize_text_field($_SESSION['cfturnstile_checkout_checked']), 'cfturnstile_checkout_check' )) {
- return;
- }
-
// Check if guest only enabled
$guest = esc_attr( get_option('cfturnstile_guest_only') );
- // Check
+ // Check — always require a fresh Turnstile token (tokens are single-use).
if( !$skip && (!$guest || ( $guest && !is_user_logged_in() )) ) {
$check = cfturnstile_check();
$success = $check['success'];
if($success != true) {
wc_add_notice( cfturnstile_failed_message(), 'error');
- } else {
- $nonce = wp_create_nonce( 'cfturnstile_checkout_check' );
- $_SESSION['cfturnstile_checkout_checked'] = $nonce;
- $cfturnstile_wc_checkout_ran = true; // Mark as executed
}
+ // Always mark as executed so the second hook doesn't re-verify
+ // the same (now consumed) token and produce duplicate errors.
+ $cfturnstile_wc_checkout_ran = true;
}
}
add_action('woocommerce_store_api_checkout_update_order_from_request', 'cfturnstile_woo_checkout_block_check', 10, 2);
function cfturnstile_woo_checkout_block_check($order, $request) {
+ // Prevent duplicate execution within a single request.
+ static $cfturnstile_wc_block_checkout_ran = false;
+ if ( $cfturnstile_wc_block_checkout_ran ) {
+ return;
+ }
+
// Skip if Turnstile disabled for payment method
$skip = 0;
if ( $request->get_method() === 'POST' ) {
@@ -177,31 +175,25 @@
}
}
- // Start session
- if (!session_id()) { session_start(); }
- // Check if already validated
- if(isset($_SESSION['cfturnstile_checkout_checked']) && wp_verify_nonce( sanitize_text_field($_SESSION['cfturnstile_checkout_checked']), 'cfturnstile_checkout_check' )) {
- return;
- }
-
// Check if guest only enabled
$guest = esc_attr( get_option('cfturnstile_guest_only') );
- // Check
+ // Check — always require a fresh Turnstile token (tokens are single-use).
if( !$skip && (!$guest || ( $guest && !is_user_logged_in() )) ) {
$extensions = $request->get_param( 'extensions' );
$token = ( is_array( $extensions ) && isset( $extensions['simple-cloudflare-turnstile']['token'] ) ) ? $extensions['simple-cloudflare-turnstile']['token'] : '';
if ( empty( $token ) ) {
+ $cfturnstile_wc_block_checkout_ran = true;
throw new Exception( cfturnstile_failed_message() );
}
$check = cfturnstile_check( $token );
$success = $check['success'];
+ // Always mark as executed so duplicate hooks don't re-verify
+ // the same (now consumed) token and produce duplicate errors.
+ $cfturnstile_wc_block_checkout_ran = true;
if($success != true) {
throw new Exception( cfturnstile_failed_message() );
- } else {
- $nonce = wp_create_nonce( 'cfturnstile_checkout_check' );
- $_SESSION['cfturnstile_checkout_checked'] = $nonce;
}
}
}
@@ -231,21 +223,7 @@
);
}
}
-// On payment complete clear session
-add_action('woocommerce_checkout_order_processed', 'cfturnstile_woo_checkout_clear', 10, 1);
-add_action('woocommerce_store_api_checkout_order_processed', 'cfturnstile_woo_checkout_clear', 10, 1);
-add_action('woocommerce_thankyou', 'cfturnstile_woo_checkout_clear', 10, 1);
-function cfturnstile_woo_checkout_clear($order_id) {
- if(isset($_SESSION['cfturnstile_checkout_checked'])) { unset($_SESSION['cfturnstile_checkout_checked']); }
-}
-// Additional clears to prevent lingering validation across session changes
-function cfturnstile_woo_clear_session() {
- if (!session_id()) { session_start(); }
- if (isset($_SESSION['cfturnstile_checkout_checked'])) { unset($_SESSION['cfturnstile_checkout_checked']); }
-}
-// Logout
-add_action('wp_logout', 'cfturnstile_woo_clear_session', 10, 0);
// Woo Checkout Pay Order Check
if(get_option('cfturnstile_woo_checkout_pay')) {
@@ -274,11 +252,8 @@
if(defined( 'REST_REQUEST' ) && REST_REQUEST) { return $user; } // Skip REST API
if(is_wp_error($user) && isset($user->errors['empty_username']) && isset($user->errors['empty_password']) ) {return $user; } // Skip Errors
- // Start session
- if (!session_id()) { session_start(); }
-
- // Check if already validated
- if(isset($_SESSION['cfturnstile_login_checked']) && wp_verify_nonce( sanitize_text_field($_SESSION['cfturnstile_login_checked']), 'cfturnstile_login_check' )) {
+ // Check if already validated (cache-friendly, no PHP session)
+ if( cfturnstile_get_verified( 'cfturnstile_login_checked' ) ) {
return $user;
}
@@ -288,17 +263,16 @@
if($success != true) {
$user = new WP_Error( 'cfturnstile_error', cfturnstile_failed_message() );
} else {
- $nonce = wp_create_nonce( 'cfturnstile_login_check' );
- $_SESSION['cfturnstile_login_checked'] = $nonce;
+ cfturnstile_set_verified( 'cfturnstile_login_checked' );
}
return $user;
}
- // Clear session on login
+ // Clear verification flag on login
add_action('wp_login', 'cfturnstile_woo_login_clear', 10, 2);
function cfturnstile_woo_login_clear($user_login, $user) {
- if(isset($_SESSION['cfturnstile_login_checked'])) { unset($_SESSION['cfturnstile_login_checked']); }
+ cfturnstile_clear_verified( 'cfturnstile_login_checked' );
}
}
}
--- a/simple-cloudflare-turnstile/inc/integrations/forms/gravity-forms.php
+++ b/simple-cloudflare-turnstile/inc/integrations/forms/gravity-forms.php
@@ -46,6 +46,7 @@
function cfturnstile_gravity_check($validation_result)
{
+ global $cfturnstile_gravity_error;
$form = $validation_result['form'];
// if whitelisted or form is disabled, return
if (cfturnstile_whitelisted() || cfturnstile_form_disable($form['id'], 'cfturnstile_gravity_disable')) {
@@ -54,7 +55,7 @@
// If not a POST request return
if ('POST' !== $_SERVER['REQUEST_METHOD']) {
- $_SESSION['cf-turnstile-response'] = cfturnstile_failed_message();
+ $cfturnstile_gravity_error = cfturnstile_failed_message();
$validation_result['is_valid'] = false;
add_filter('gform_validation_message_' . $form['id'], 'cfturnstile_gravity_validation_message', 10, 2);
return $validation_result;
@@ -64,7 +65,7 @@
$success = $check['success'];
// if check fails, return error
if ($success != true) {
- $_SESSION['cf-turnstile-response'] = cfturnstile_failed_message();
+ $cfturnstile_gravity_error = cfturnstile_failed_message();
$validation_result['is_valid'] = false;
add_filter('gform_validation_message_' . $form['id'], 'cfturnstile_gravity_validation_message', 10, 2);
@@ -76,9 +77,10 @@
function cfturnstile_gravity_validation_message($message, $form)
{
- if (isset($_SESSION['cf-turnstile-response'])) {
- $error = $_SESSION['cf-turnstile-response'];
- unset($_SESSION['cf-turnstile-response']);
+ global $cfturnstile_gravity_error;
+ if (isset($cfturnstile_gravity_error)) {
+ $error = $cfturnstile_gravity_error;
+ $cfturnstile_gravity_error = null;
$message = '<div class="gform_validation_errors" id="gform_' . $form['id'] . '_validation_container">
<h2 class="gform_submission_error hide_summary"><span class="gform-icon gform-icon--close"></span>
--- a/simple-cloudflare-turnstile/inc/integrations/membership/memberpress.php
+++ b/simple-cloudflare-turnstile/inc/integrations/membership/memberpress.php
@@ -33,12 +33,9 @@
$LimitedToProductIDs = get_option('cfturnstile_mepr_product_ids');
$ProductsNeedingCaptcha = explode("n", str_replace("r", "", $LimitedToProductIDs));
- // Start session
- if (!session_id()) { session_start(); }
-
- // Check if already validated
- if(isset($_SESSION['cfturnstile_login_checked']) && wp_verify_nonce( sanitize_text_field($_SESSION['cfturnstile_login_checked']), 'cfturnstile_login_check' )) {
- unset($_SESSION['cfturnstile_login_checked']);
+ // Check if already validated (cache-friendly, no PHP session)
+ if( cfturnstile_get_verified( 'cfturnstile_login_checked' ) ) {
+ cfturnstile_clear_verified( 'cfturnstile_login_checked' );
return $errors;
}
@@ -59,8 +56,7 @@
if($success != true) {
$errors[] = cfturnstile_failed_message();
} else {
- $nonce = wp_create_nonce( 'cfturnstile_login_check' );
- $_SESSION['cfturnstile_login_checked'] = $nonce;
+ cfturnstile_set_verified( 'cfturnstile_login_checked' );
}
} else {
$errors[] = cfturnstile_failed_message();
--- a/simple-cloudflare-turnstile/inc/integrations/membership/ultimate-member.php
+++ b/simple-cloudflare-turnstile/inc/integrations/membership/ultimate-member.php
@@ -17,9 +17,9 @@
if(get_option('cfturnstile_um_password')) { add_action( 'um_reset_password_errors_hook', 'cfturnstile_um_check', 20, 1 ); }
function cfturnstile_um_check( $args ) {
- // Check if already validated
- if(isset($_SESSION['cfturnstile_login_checked']) && wp_verify_nonce( sanitize_text_field($_SESSION['cfturnstile_login_checked']), 'cfturnstile_login_check' )) {
- unset($_SESSION['cfturnstile_login_checked']);
+ // Check if already validated (cache-friendly, no PHP session)
+ if( cfturnstile_get_verified( 'cfturnstile_login_checked' ) ) {
+ cfturnstile_clear_verified( 'cfturnstile_login_checked' );
return;
}
@@ -35,8 +35,7 @@
if($success != true) {
UM()->form()->add_error( 'cfturnstile', cfturnstile_failed_message() );
} else {
- $nonce = wp_create_nonce( 'cfturnstile_login_check' );
- $_SESSION['cfturnstile_login_checked'] = $nonce;
+ cfturnstile_set_verified( 'cfturnstile_login_checked' );
}
} else {
UM()->form()->add_error( 'cfturnstile', cfturnstile_failed_message() );
@@ -48,8 +47,8 @@
function cfturnstile_um_error_message() {
echo '<p style="color: red; font-weight: bold;">' . cfturnstile_failed_message() . '</p>';
}
-// Clear session on login
+// Clear verification flag on login
add_action('um_user_login', 'cfturnstile_um_login_clear', 10, 1);
function cfturnstile_um_login_clear($args) {
- if(isset($_SESSION['cfturnstile_login_checked'])) { unset($_SESSION['cfturnstile_login_checked']); }
+ cfturnstile_clear_verified( 'cfturnstile_login_checked' );
}
No newline at end of file
--- a/simple-cloudflare-turnstile/inc/turnstile.php
+++ b/simple-cloudflare-turnstile/inc/turnstile.php
@@ -248,12 +248,35 @@
$results['success'] = false;
}
- foreach ($response as $key => $val) {
- if ($key == 'error-codes') {
- foreach ($val as $key => $error_val) {
+ foreach ( $response as $key => $val ) {
+ if ( 'error-codes' === $key ) {
+ foreach ( $val as $key => $error_val ) {
$results['error_code'] = $error_val;
- if($error_val == 'invalid-input-secret') {
- update_option('cfturnstile_tested', 'no'); // Disable if invalid secret
+ if ( 'invalid-input-secret' === $error_val ) {
+ // Rate-limit: only process once per 5 minutes to avoid repeated DB writes on high-traffic sites.
+ if ( false === get_transient( 'cfturnstile_invalid_secret_throttle' ) ) {
+ set_transient( 'cfturnstile_invalid_secret_throttle', 1, 5 * MINUTE_IN_SECONDS );
+ $already_flagged = ( 'no' === get_option( 'cfturnstile_soft_tested' ) );
+ update_option( 'cfturnstile_invalid_secret_notice', '1' );
+ update_option( 'cfturnstile_soft_tested', 'no' );
+ if ( ! $already_flagged ) {
+ $admin_email = get_option( 'admin_email' );
+ $site_name = get_bloginfo( 'name' );
+ $settings_url = admin_url( 'options-general.php?page=cfturnstile' );
+ $subject = sprintf(
+ /* translators: %s: Site name. */
+ __( '[%s] Cloudflare Turnstile: Invalid Secret Key Detected', 'simple-cloudflare-turnstile' ),
+ $site_name
+ );
+ $message = sprintf(
+ /* translators: 1: Site name, 2: Settings page URL. */
+ __( "Cloudflare has reported that the Turnstile secret key on %1$s is invalid (error: invalid-input-secret).nnTurnstile is still active on your forms, but verifications may be failing until the key is corrected.nnPlease check your API keys on the settings page:n%2$s", 'simple-cloudflare-turnstile' ),
+ $site_name,
+ $settings_url
+ );
+ wp_mail( $admin_email, $subject, $message );
+ }
+ }
}
}
}
--- a/simple-cloudflare-turnstile/inc/verification.php
+++ b/simple-cloudflare-turnstile/inc/verification.php
@@ -0,0 +1,64 @@
+<?php
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+/**
+ * Build a transient key from the Turnstile token in the current POST.
+ *
+ * @param string $key Verification key, e.g. 'cfturnstile_checkout_checked'.
+ * @return string|false Transient key, or false if no token is present.
+ */
+function cfturnstile_transient_key( $key ) {
+ $token = isset( $_POST['cf-turnstile-response'] ) ? sanitize_text_field( $_POST['cf-turnstile-response'] ) : '';
+ if ( $token ) {
+ return 'cft_' . substr( md5( $key . '_t' . $token ), 0, 20 );
+ }
+
+ return false;
+}
+
+/**
+ * Store a verification flag tied to the current Turnstile token.
+ *
+ * Uses a short-lived transient keyed to the token so each token can only
+ * be used once. Turnstile tokens are single-use by design.
+ *
+ * @param string $key Verification key, e.g. 'cfturnstile_checkout_checked'.
+ * @param string $context Reserved for future use (default 'default').
+ */
+function cfturnstile_set_verified( $key, $context = 'default' ) {
+ $transient_key = cfturnstile_transient_key( $key );
+ if ( $transient_key ) {
+ set_transient( $transient_key, 1, 20 );
+ }
+}
+
+/**
+ * Check whether a verification flag is set for the current Turnstile token.
+ *
+ * @param string $key Verification key, e.g. 'cfturnstile_checkout_checked'.
+ * @param string $context Reserved for future use (default 'default').
+ * @return bool
+ */
+function cfturnstile_get_verified( $key, $context = 'default' ) {
+ $transient_key = cfturnstile_transient_key( $key );
+ if ( $transient_key ) {
+ return (bool) get_transient( $transient_key );
+ }
+
+ return false;
+}
+
+/**
+ * Clear a verification flag.
+ *
+ * @param string $key Verification key.
+ * @param string $context Reserved for future use (default 'default').
+ */
+function cfturnstile_clear_verified( $key, $context = 'default' ) {
+ $transient_key = cfturnstile_transient_key( $key );
+ if ( $transient_key ) {
+ delete_transient( $transient_key );
+ }
+}
--- a/simple-cloudflare-turnstile/inc/wordpress.php
+++ b/simple-cloudflare-turnstile/inc/wordpress.php
@@ -7,9 +7,7 @@
* Display the turnstile field on the login form.
*/
function cfturnstile_field_login() {
- if(isset($_SESSION['cfturnstile_login_checked'])) {
- unset($_SESSION['cfturnstile_login_checked']);
- }
+ cfturnstile_clear_verified( 'cfturnstile_login_checked' );
if(get_option('cfturnstile_login_only', 0)) {
$login_url_path = wp_parse_url(wp_login_url(), PHP_URL_PATH);
$current_url_path = wp_parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
@@ -62,14 +60,11 @@
return $user;
}
- // Start session
- if (!session_id()) { session_start(); }
-
// Check if already validated
- if(isset($user->ID) && isset($_SESSION['cfturnstile_login_checked']) && wp_verify_nonce( sanitize_text_field($_SESSION['cfturnstile_login_checked']), 'cfturnstile_login_check' )) {
+ if(isset($user->ID) && cfturnstile_get_verified( 'cfturnstile_login_checked' ) ) {
return $user;
} else {
- unset($_SESSION['cfturnstile_login_checked']);
+ cfturnstile_clear_verified( 'cfturnstile_login_checked' );
}
// Check Turnstile
@@ -80,18 +75,17 @@
do_action('cfturnstile_wp_login_failed');
} else {
if (isset($user->ID)) {
- $nonce = wp_create_nonce( 'cfturnstile_login_check' );
- $_SESSION['cfturnstile_login_checked'] = $nonce;
+ cfturnstile_set_verified( 'cfturnstile_login_checked' );
}
}
return $user;
}
- // Clear session on login
+ // Clear verification flag on login
add_action('wp_login', 'cfturnstile_wp_login_clear', 10, 2);
function cfturnstile_wp_login_clear($user_login, $user) {
- if(isset($_SESSION['cfturnstile_login_checked'])) { unset($_SESSION['cfturnstile_login_checked']); }
+ cfturnstile_clear_verified( 'cfturnstile_login_checked' );
}
/* Hook into wp_login_form() to add the Turnstile field */
function cfturnstile_wp_login_form_field($content = "", $args = array()) {
--- a/simple-cloudflare-turnstile/simple-cloudflare-turnstile.php
+++ b/simple-cloudflare-turnstile/simple-cloudflare-turnstile.php
@@ -2,7 +2,7 @@
/**
* Plugin Name: Simple CAPTCHA Alternative with Cloudflare Turnstile
* Description: Easily add Cloudflare Turnstile to your WordPress forms. The user-friendly, privacy-preserving CAPTCHA alternative.
- * Version: 1.38.0
+ * Version: 1.38.1
* Author: Elliot Sowersby, RelyWP
* Author URI: https://www.relywp.com
* License: GPLv3 or later
@@ -121,6 +121,7 @@
* Include Functions
*/
include_once(plugin_dir_path(__FILE__) . 'inc/failsafe.php');
+ include_once(plugin_dir_path(__FILE__) . 'inc/verification.php');
include_once(plugin_dir_path(__FILE__) . 'inc/turnstile.php');
/**
--- a/simple-cloudflare-turnstile/uninstall.php
+++ b/simple-cloudflare-turnstile/uninstall.php
@@ -17,6 +17,12 @@
}
// Remove the "cfturnstile_tested" option
delete_option('cfturnstile_tested');
+ // Remove the "cfturnstile_invalid_secret_notice" option
+ delete_option( 'cfturnstile_invalid_secret_notice' );
+ // Remove the "cfturnstile_soft_tested" option
+ delete_option( 'cfturnstile_soft_tested' );
+ // Remove the throttle transient
+ delete_transient( 'cfturnstile_invalid_secret_throttle' );
// Remove the "cfturnstile_uninstall_remove" option itself
delete_option('cfturnstile_uninstall_remove');
}
No newline at end of file