Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion admin/partials/dashboard-widget.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
<p>
<strong><?php esc_html_e('Want more intelligence?', 'webdecoy'); ?></strong>
<?php esc_html_e('Connect to WebDecoy Cloud for IP reputation, VPN detection, and cross-site threat data.', 'webdecoy'); ?>
<a href="<?php echo esc_url(admin_url('admin.php?page=webdecoy#tab-cloud')); ?>">
<a href="<?php echo esc_url(admin_url('admin.php?page=webdecoy&tab=cloud')); ?>">
<?php esc_html_e('Learn more', 'webdecoy'); ?>
</a>
</p>
Expand Down
4 changes: 2 additions & 2 deletions admin/partials/statistics-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@
<div class="webdecoy-cloud-upsell">
<h3><?php esc_html_e('Want deeper insights?', 'webdecoy'); ?></h3>
<p><?php esc_html_e('WebDecoy Cloud provides IP reputation scoring, VPN/proxy detection, geographic analysis, and indefinite data retention. Local data is automatically cleaned up after 30 days.', 'webdecoy'); ?></p>
<a href="https://webdecoy.com/pricing" class="button button-primary" target="_blank" rel="noopener">
<?php esc_html_e('Explore WebDecoy Cloud', 'webdecoy'); ?>
<a href="<?php echo esc_url(admin_url('admin.php?page=webdecoy&tab=cloud')); ?>" class="button button-primary">
<?php esc_html_e('Connect to WebDecoy Cloud', 'webdecoy'); ?>
</a>
</div>
<?php endif; ?>
Expand Down
5 changes: 5 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
*** WebDecoy Bot Detection Changelog ***

= 2.4.1 - 2026-08-17 =
* Fixed: cloud features switch on immediately after one-click connect. The connection itself succeeded, but the premium status stayed off until a later background revalidation, so the JS verification token and cloud reporting were silently inactive at the exact moment you had just connected.
* Fixed: the dashboard widget's "Learn more" link landed on the Protection tab instead of the WebDecoy Cloud tab.
* Changed: the Statistics page upsell now opens the in-admin Cloud connect tab instead of leaving your site for the pricing page.

= 2.4.0 - 2026-07-30 =
* Added: filter rules can read the WebDecoy edge validator's verdict through new edge.* fields — edge.class, edge.clearance, edge.present, plus the shorthands edge.verified / edge.crawler / edge.script / edge.browser. edge.class is one of: verified (an identity Cloudflare attested, such as Googlebot — never degrade these), crawler (says it is a crawler, unproven), script (an HTTP client library, not a browser), or browser (nothing non-human fired). Matching this was already possible as req.header("x-wd-class") because the plugin forwards every request header into the rule context, but nothing told you the header existed or what its values meant, so nobody used it. The Rules screen now lists the fields and explains them. Absence is deliberately not a class: if the validator is not in front of a request, edge.present is false and every edge.* condition is false, which means "no information" rather than "human" — a rule using these decides whether to serve someone less, so guessing would be the wrong default. A value we do not recognise is ignored rather than passed through. Safe to use for blocking, throttling, logging and metering; not safe for serving different page content on a cacheable URL, because Cloudflare's cache key ignores this header outside Enterprise plans, so the first cached version would be served to everyone including Googlebot — the Rules screen says so too.

Expand Down
7 changes: 6 additions & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Donate link: https://webdecoy.com
Tags: bot detection, security, spam protection, woocommerce, ai bots
Requires at least: 6.1
Tested up to: 7.0
Stable tag: 2.4.0
Stable tag: 2.4.1
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Expand Down Expand Up @@ -222,6 +222,11 @@ The bundled good-bot list (sdk/src/GoodBotList.php) stores a documentation URL f

== Changelog ==

= 2.4.1 =
* Fixed: cloud features switch on immediately after one-click connect. The connection itself succeeded, but the premium status stayed off until a later background revalidation, so the JS verification token and cloud reporting were silently inactive at the exact moment you had just connected.
* Fixed: the dashboard widget's "Learn more" link landed on the Protection tab instead of the WebDecoy Cloud tab.
* Changed: the Statistics page upsell now opens the in-admin Cloud connect tab instead of leaving your site for the pricing page.

= 2.4.0 =
* Added: filter rules can read what the WebDecoy edge validator concluded about a request, using new edge.* fields: edge.class, edge.clearance, edge.present, and the shorthands edge.verified / edge.crawler / edge.script / edge.browser. edge.class is one of: verified (an identity Cloudflare attested, such as Googlebot, never degrade these), crawler (says it is a crawler, unproven), script (an HTTP client library, not a browser), or browser (nothing non-human fired). This was always matchable as req.header("x-wd-class"), but nothing said so; the Rules screen now documents the fields and what each value means. If the validator is not in front of a request, edge.present is false and every edge.* condition is false. That means "no information", not "human". Safe for blocking, throttling, logging and metering; the Rules screen also explains why you should not use it to serve different page content on a cacheable URL.

Expand Down
16 changes: 12 additions & 4 deletions webdecoy.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: WebDecoy Bot Detection
* Plugin URI: https://webdecoy.com/wordpress
* Description: Protect your WordPress site from bots, spam, and carding attacks with WebDecoy's advanced threat detection.
* Version: 2.4.0
* Version: 2.4.1
* Requires at least: 6.1
* Requires PHP: 7.4
* Author: WebDecoy
Expand Down Expand Up @@ -41,7 +41,7 @@
}

// Plugin constants
define('WEBDECOY_VERSION', '2.4.0');
define('WEBDECOY_VERSION', '2.4.1');
define('WEBDECOY_PLUGIN_FILE', __FILE__);
define('WEBDECOY_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WEBDECOY_PLUGIN_URL', plugin_dir_url(__FILE__));
Expand Down Expand Up @@ -1648,7 +1648,7 @@
],
];

$wpdb->insert($wpdb->prefix . 'webdecoy_detections', [

Check warning on line 1651 in webdecoy.php

View workflow job for this annotation

GitHub Actions / PHP Coding Standards

Use of a direct database call is discouraged.
'ip_address' => $ip,
'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '',
'score' => 100,
Expand Down Expand Up @@ -1689,7 +1689,7 @@
),
];

$wpdb->insert($wpdb->prefix . 'webdecoy_detections', [

Check warning on line 1692 in webdecoy.php

View workflow job for this annotation

GitHub Actions / PHP Coding Standards

Use of a direct database call is discouraged.
'ip_address' => $violation->ip,
'user_agent' => $violation->userAgent ?? '',
'score' => $confidence,
Expand Down Expand Up @@ -1839,7 +1839,7 @@
'metadata' => $result->getMetadata(),
];

$wpdb->insert($table, [

Check warning on line 1842 in webdecoy.php

View workflow job for this annotation

GitHub Actions / PHP Coding Standards

Use of a direct database call is discouraged.
'ip_address' => $ip,
'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '',
'score' => $result->getScore(),
Expand Down Expand Up @@ -1955,7 +1955,7 @@
$ip = $this->get_client_ip();

global $wpdb;
$wpdb->insert($wpdb->prefix . 'webdecoy_detections', [

Check warning on line 1958 in webdecoy.php

View workflow job for this annotation

GitHub Actions / PHP Coding Standards

Use of a direct database call is discouraged.
'ip_address' => $ip,
'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '',
'score' => 100,
Expand Down Expand Up @@ -2681,7 +2681,7 @@
$threat_level = 'LOW';
}

$wpdb->insert($table, [

Check warning on line 2684 in webdecoy.php

View workflow job for this annotation

GitHub Actions / PHP Coding Standards

Use of a direct database call is discouraged.
'ip_address' => $ip,
'user_agent' => $user_agent,
'score' => $score,
Expand Down Expand Up @@ -3300,8 +3300,16 @@
$this->options['api_key'] = $this->is_encrypted($api_key) ? $this->decrypt_value($api_key) : $api_key;
}

// Force a fresh API status check on next use now that creds changed.
$this->clear_api_status_cache();
// The only caller is the connect flow, which reaches here immediately
// after a successful token exchange against the API — the key is
// known-good right now. Mark the status active instead of merely
// clearing the cache: with only a clear, is_premium() stays false
// until something happens to trigger a revalidation, which keeps the
// JS verification token and violation reporting off at the exact
// moment the user just connected and is watching. (update_options_raw
// above already fired the option hook that clears the cache, so this
// set is what survives.)
$this->set_api_status_cache('active');
}

/**
Expand Down
Loading