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
25 changes: 25 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,28 @@ always point at a ZIP that actually exists there with a matching SHA-256.
git tag -a v<version> -m "v<version> — <summary>"
git push origin v<version>
```

## 5. WordPress.org SVN release

The directory listing at <https://wordpress.org/plugins/webdecoy> is driven by
the SVN repo (`https://plugins.svn.wordpress.org/webdecoy`). A working copy
lives at `.svn-wporg/` (git-ignored, excluded from builds). Credentials:
username `webdecoy1`, SVN password set separately at
<https://profiles.wordpress.org/me/profile/edit/group/3/?screen=svn-password>.

```bash
./build.sh <version> --org
rm -rf .svn-wporg/trunk/* && unzip -q dist/webdecoy-<version>-wporg.zip -d /tmp/wporg
cp -R /tmp/wporg/webdecoy/. .svn-wporg/trunk/ && rm -rf /tmp/wporg
cd .svn-wporg
svn add --force trunk assets
svn status # sanity-check: no unexpected deletes/adds; `svn rm` any removed files
svn ci -m "Release <version>" --username webdecoy1
svn cp trunk tags/<version>
svn ci -m "Tag <version>" --username webdecoy1
```

`readme.txt`'s `Stable tag:` must match the SVN tag name — the directory serves
whatever tag `Stable tag:` in `trunk/readme.txt` points at. Listing images
(icon/banner PNGs, regenerated from `assets/*.svg` per `assets/README.md`) and
`screenshot-N.png` files go in the SVN top-level `assets/` dir, not trunk.
9 changes: 7 additions & 2 deletions assets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ rsvg-convert -w 772 -h 250 banner.svg > banner-772x250.png

## Notes

- The icon uses a shield with a web/honeycomb pattern in dark navy and green.
- The banner uses a dark gradient background with the plugin name and tagline.
- Both assets use the WebDecoy duck mascot (white duck, pink hoodie, shades) —
the same artwork as `frontend/src/assets/duck-logo.svg` in the app monorepo,
embedded as a base64 PNG. Brand colors: hoodie pink `#F90289`, ink
`#111C26`, bill orange `#F99717`.
- The banner wordmark/tagline are live `<text>` set in Avenir Next — render the
PNGs on macOS (or a machine with Avenir Next installed) or the type falls
back to a different face.
- Upload the generated PNGs (not the SVGs) to the WordPress.org SVN `assets/`
directory. SVG files are kept here as editable sources only.
112 changes: 10 additions & 102 deletions assets/banner.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 4 additions & 44 deletions assets/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions cdn-files/plugin-info.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"name": "WebDecoy Bot Detection",
"slug": "webdecoy",
"version": "2.2.2",
"version": "2.3.0",
"author": "<a href=\"https://webdecoy.com\">WebDecoy</a>",
"author_profile": "https://webdecoy.com",
"requires": "5.6",
"tested": "6.7",
"requires": "6.1",
"tested": "7.0",
"requires_php": "7.4",
"download_url": "https://cdn.webdecoy.com/wordpress/webdecoy-2.2.2.zip",
"download_url": "https://cdn.webdecoy.com/wordpress/webdecoy-2.3.0.zip",
"sections": {
"description": "<p>WebDecoy provides enterprise-grade bot detection and fraud protection for WordPress websites. Unlike simple CAPTCHA solutions, WebDecoy uses a layered defense approach that analyzes visitors from multiple angles including deterministic tripwires that catch scanners with zero false positives.</p><h4>Key Features</h4><ul><li>Deterministic tripwires (hidden honeypot paths) zero-false-positive bot blocking</li><li>Server-side and client-side bot detection</li><li>Invisible proof-of-work challenge (no external CAPTCHA service)</li><li>Comment, login, and registration spam protection</li><li>WooCommerce carding attack prevention</li><li>60+ good bots automatically allowed</li><li>AI crawler detection and blocking</li><li>Optional WebDecoy Cloud: centralized dashboard and rotation-proof device lockouts</li></ul>",
"installation": "<ol><li>Upload the plugin files to <code>/wp-content/plugins/webdecoy</code></li><li>Activate the plugin through the Plugins menu</li><li>Tripwires and local protection are active out of the box no API key required</li><li>Optionally go to WebDecoy &gt; Settings &gt; WebDecoy Cloud to connect for centralized monitoring and enforcement</li></ol>",
"changelog": "<h4>2.1.0</h4><ul><li>JS execution verification to catch non-JS HTTP scrapers</li><li>Challenge token meta tag on page serve; automatic page-serve reporting</li></ul><h4>2.0.0</h4><ul><li>All detection and protection now works locally no API key required</li><li>Invisible proof-of-work challenge system (SHA-256, no external service)</li><li>Behavioral scoring, statistics page, enhanced detections page</li></ul><h4>1.3.0</h4><ul><li>Bulk IP blocking/unblocking; enhanced good bot detection (60+ bots)</li></ul>",
"description": "<p>WebDecoy provides enterprise-grade bot detection and fraud protection for WordPress websites. Unlike simple CAPTCHA solutions, WebDecoy uses a layered defense approach that analyzes visitors from multiple angles \u2014 including deterministic tripwires that catch scanners with zero false positives.</p><h4>Key Features</h4><ul><li>Deterministic tripwires (hidden honeypot paths) \u2014 zero-false-positive bot blocking</li><li>Server-side and client-side bot detection</li><li>Invisible proof-of-work challenge (no external CAPTCHA service)</li><li>Comment, login, and registration spam protection</li><li>WooCommerce carding attack prevention</li><li>60+ good bots automatically allowed</li><li>AI crawler detection and blocking</li><li>Optional WebDecoy Cloud: centralized dashboard and rotation-proof device lockouts</li></ul>",
"installation": "<ol><li>Upload the plugin files to <code>/wp-content/plugins/webdecoy</code></li><li>Activate the plugin through the Plugins menu</li><li>Tripwires and local protection are active out of the box \u2014 no API key required</li><li>Optionally go to WebDecoy &gt; Settings &gt; WebDecoy Cloud to connect for centralized monitoring and enforcement</li></ol>",
"changelog": "<h4>2.3.0</h4><ul><li>One-click WebDecoy Cloud connect with automatic key provisioning</li><li>Monthly security report opt-in</li><li>Plan entitlements sync (fails open to free)</li><li>Fixed: Statistics charts growing unbounded with detection data</li></ul><h4>2.1.0</h4><ul><li>JS execution verification to catch non-JS HTTP scrapers</li><li>Challenge token meta tag on page serve; automatic page-serve reporting</li></ul><h4>2.0.0</h4><ul><li>All detection and protection now works locally \u2014 no API key required</li><li>Invisible proof-of-work challenge system (SHA-256, no external service)</li><li>Behavioral scoring, statistics page, enhanced detections page</li></ul><h4>1.3.0</h4><ul><li>Bulk IP blocking/unblocking; enhanced good bot detection (60+ bots)</li></ul>",
"faq": "<h4>Does WebDecoy slow down my site?</h4><p>No. WebDecoy adds negligible latency; tripwire checks are a fast path lookup and clearance minting is idle-deferred.</p><h4>Will it block search engines?</h4><p>No. WebDecoy automatically allows 60+ known good bots including all major search engines, and tripwires only fire on hidden paths no legitimate crawler follows.</p>"
},
"icons": {
Expand Down
6 changes: 6 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
*** WebDecoy Bot Detection Changelog ***

= 2.3.0 - 2026-07-23 =
* Added: One-click WebDecoy Cloud connect (Settings → WebDecoy Cloud). Clicking Connect opens app.webdecoy.com to approve; on return the plugin exchanges a one-time token server-side and stores the provisioned API keys (encrypted at rest). Manual API key entry remains available under "Advanced: manual configuration".
* Added: "Send me a monthly security report" opt-in at connect time.
* Added: Plan entitlements sync (twice daily via cron) — a feature switchboard for upcoming plan-aware capabilities; any sync error fails open to the free tier.
* Fixed: Statistics page charts grew unbounded (thousands of pixels tall) once detection data existed — Chart.js canvases are now wrapped in fixed-height containers.

= 2.2.3 - 2026-07-21 =
* Changed: All CSS and JavaScript is now loaded via the WordPress dependency APIs — the challenge/block interstitials use wp_register_style/script + wp_print_styles/scripts with static asset files (public/css/, public/js/webdecoy-challenge.js), and the Statistics page attaches chart data via wp_add_inline_script. No more raw <style>/<script> tags.
* Changed: The "Protected by WebDecoy" credit on the challenge page is now an explicit admin opt-in (Settings → Blocking → Challenge Page Credit) and off by default, per WordPress.org guideline 10.
Expand Down
20 changes: 14 additions & 6 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Donate link: https://webdecoy.com
Tags: security, bot detection, spam protection, woocommerce, firewall
Requires at least: 6.1
Tested up to: 7.0
Stable tag: 2.2.3
Stable tag: 2.3.0
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Expand Down Expand Up @@ -109,8 +109,8 @@ The threshold is fully configurable to match your site's needs.
= Optional: Connect to WebDecoy Cloud =

1. Go to **WebDecoy > Settings > WebDecoy Cloud** tab
2. Enter your API key from your [WebDecoy dashboard](https://app.webdecoy.com)
3. Click "Test Connection" to verify
2. Click **Connect to WebDecoy Cloud** — you approve the connection on app.webdecoy.com and are returned automatically; your API keys are provisioned for you
3. Prefer manual setup? Expand **Advanced: manual configuration** and enter an API key from your [WebDecoy dashboard](https://app.webdecoy.com)
4. Cloud features (threat intel, VPN detection, etc.) activate automatically

== Frequently Asked Questions ==
Expand Down Expand Up @@ -157,12 +157,14 @@ When a suspicious visitor is detected and your block action is set to "Challenge

== External Services ==

This plugin can optionally connect to the following external services when you provide an API key:
This plugin can optionally connect to the following external services when you connect a WebDecoy Cloud account — either with the one-click Connect button or by entering an API key manually:

= WebDecoy Cloud — ingest.webdecoy.com and api.webdecoy.com =
This plugin only contacts WebDecoy Cloud when you explicitly connect an account by entering an API key on the WebDecoy Cloud settings tab. With no API key configured, no data is ever sent to these services.
= WebDecoy Cloud — app.webdecoy.com, api.webdecoy.com and ingest.webdecoy.com =
This plugin only contacts WebDecoy Cloud after you explicitly start a connection on the WebDecoy Cloud settings tab. With no connection made and no API key configured, no data is ever sent to these services.

What is sent, and when:
* When you click "Connect to WebDecoy Cloud": your browser is redirected to app.webdecoy.com to approve the connection (carrying your site URL, site name, a one-time nonce, and your monthly-report preference). After you approve, the plugin exchanges a one-time token with api.webdecoy.com (sending the token, your site URL and the nonce) to receive the site's API keys. Cancelling sends nothing further.
* After connecting: the plugin fetches your plan entitlements from ingest.webdecoy.com (authenticated with your API key) twice daily.
* When a detection or rule violation occurs: the visitor's IP address, user agent, request path, threat score and detection flags are sent to ingest.webdecoy.com so the event appears in your cloud dashboard.
* When you use an IP-reputation filter rule (e.g. ip.abuse_score, ip.tor): the visitor's IP address is sent to ingest.webdecoy.com to look up reputation/geo data.
* When validating your key or forwarding a WooCommerce checkout detection: your API key, organization ID and the detection data above are sent to api.webdecoy.com / ingest.webdecoy.com.
Expand Down Expand Up @@ -192,6 +194,12 @@ The bundled good-bot list (sdk/src/GoodBotList.php) stores a documentation URL f

== Changelog ==

= 2.3.0 =
* Added: One-click WebDecoy Cloud connect — approve on app.webdecoy.com and your API keys are provisioned automatically; manual key entry moved under "Advanced: manual configuration"
* Added: Optional monthly security report opt-in when connecting
* Added: Plan entitlements sync after connecting (twice daily, fails open to the free tier)
* Fixed: Statistics page charts could grow endlessly tall once detection data existed (Chart.js containers now have a fixed height)

= 2.2.3 =
* Changed: All CSS and JavaScript is now loaded via the WordPress dependency APIs (wp_register_style/script, wp_add_inline_script, wp_print_styles/scripts) — no more raw style/script tags
* Changed: The "Protected by WebDecoy" credit on the challenge page is now opt-in (Settings > Blocking) and off by default
Expand Down
4 changes: 2 additions & 2 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.2.3
* Version: 2.3.0
* 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.2.3');
define('WEBDECOY_VERSION', '2.3.0');
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 @@ -1252,7 +1252,7 @@
],
];

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

Check warning on line 1255 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 @@ -1293,7 +1293,7 @@
),
];

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

Check warning on line 1296 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 @@ -1431,7 +1431,7 @@
'metadata' => $result->getMetadata(),
];

$wpdb->insert($table, [

Check warning on line 1434 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 @@ -1533,7 +1533,7 @@
$ip = $this->get_client_ip();

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

Check warning on line 1536 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 @@ -2243,7 +2243,7 @@
$threat_level = 'LOW';
}

$wpdb->insert($table, [

Check warning on line 2246 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
Loading