From b3976521eabddffeb1ac2dcf5b857749e950f340 Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Tue, 5 May 2026 15:35:56 +0200 Subject: [PATCH 1/4] Improved: hardened Proxy Speed Module, to make sure it doesn't disable plugins on non-proxy requests. --- mu-plugin/plausible-proxy-speed-module.php | 48 +++++++++++++++------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/mu-plugin/plausible-proxy-speed-module.php b/mu-plugin/plausible-proxy-speed-module.php index 3907e93f..9c29dd89 100644 --- a/mu-plugin/plausible-proxy-speed-module.php +++ b/mu-plugin/plausible-proxy-speed-module.php @@ -4,7 +4,7 @@ * Description: Speeds up Plausible Analytics' proxy for avoiding ad blockers. * Plugin URI: https://plausible.io * Author: Plausible HQ - * Version: 1.0.0 + * Version: 1.0.1 * Author URI: https://plausible.io * * Text Domain: plausible-analytics @@ -12,18 +12,18 @@ class PlausibleProxySpeed { /** - * Is current request a request to our proxy? + * Is the current request a request to our proxy? * * @var bool */ - private $is_proxy_request = false; + private $is_proxy_request; /** * Current request URI. * * @var string */ - private $request_uri = ''; + private $request_uri; /** * Build properties. @@ -38,27 +38,44 @@ public function __construct() { } /** - * Helper method to retrieve Request URI. Checks several globals. + * Helper method to retrieve Request URI. * - * @return mixed + * @return string */ private function get_request_uri() { - return $_SERVER[ 'REQUEST_URI' ]; + return $_SERVER['REQUEST_URI'] ?? ''; } /** - * Check if current request is a proxy request. + * Check if the current request is a proxy request. + * + * The namespace must appear as a path segment under the REST prefix + * (e.g. /wp-json/[/...]). Substring matches in query + * strings, fragments, or unrelated path segments are rejected. * * @return bool */ private function is_proxy_request() { - $namespace = get_option( 'plausible_analytics_proxy_resources' )[ 'namespace' ] ?? ''; + $namespace = get_option( 'plausible_analytics_proxy_resources' )['namespace'] ?? ''; if ( ! $namespace ) { return false; } - return strpos( $this->request_uri, $namespace ) !== false; + $path = parse_url( $this->request_uri, PHP_URL_PATH ); + + if ( ! is_string( $path ) || $path === '' ) { + return false; + } + + $rest_prefix = function_exists( 'rest_get_url_prefix' ) + ? trim( rest_get_url_prefix(), '/' ) + : 'wp-json'; + + $expected = '/' . $rest_prefix . '/' . trim( $namespace, '/' ); + + return $path === $expected + || str_starts_with( $path, $expected . '/' ); } /** @@ -73,6 +90,10 @@ private function init() { /** * Filter the list of active plugins for custom endpoint requests. * + * Uses basename() exact-match comparison instead of strpos(), so a + * plugin file path can only match if its filename is exactly in the + * allowlist. + * * @param array $active_plugins The list of active plugins. * * @return array The filtered list of active plugins. @@ -86,11 +107,8 @@ public function filter_active_plugins( $active_plugins ) { $filtered_plugins = []; foreach ( $active_plugins as $plugin ) { - foreach ( $allowed_plugin_files as $allowed_plugin_file ) { - if ( strpos( $plugin, $allowed_plugin_file ) !== false ) { - $filtered_plugins[] = $plugin; - break; - } + if ( in_array( basename( $plugin ), $allowed_plugin_files, true ) ) { + $filtered_plugins[] = $plugin; } } From 0c26b9431616c7a9b44a5a26d6c5d5b3bbfb6970 Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Tue, 5 May 2026 15:53:30 +0200 Subject: [PATCH 2/4] Improved: Handle WordPress subdirectory installs in the REST-path match. Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- mu-plugin/plausible-proxy-speed-module.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mu-plugin/plausible-proxy-speed-module.php b/mu-plugin/plausible-proxy-speed-module.php index 9c29dd89..41d59f16 100644 --- a/mu-plugin/plausible-proxy-speed-module.php +++ b/mu-plugin/plausible-proxy-speed-module.php @@ -68,11 +68,9 @@ private function is_proxy_request() { return false; } - $rest_prefix = function_exists( 'rest_get_url_prefix' ) - ? trim( rest_get_url_prefix(), '/' ) - : 'wp-json'; - - $expected = '/' . $rest_prefix . '/' . trim( $namespace, '/' ); + $expected = function_exists( 'rest_url' ) + ? untrailingslashit( (string) wp_parse_url( rest_url( trim( $namespace, '/' ) ), PHP_URL_PATH ) ) + : '/wp-json/' . trim( $namespace, '/' ); return $path === $expected || str_starts_with( $path, $expected . '/' ); From c6dc08a09ed53ecff9d09681a1ad7c043dee8479 Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Tue, 5 May 2026 15:57:39 +0200 Subject: [PATCH 3/4] Updated mu-plugin. --- src/Admin/Upgrades.php | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/Admin/Upgrades.php b/src/Admin/Upgrades.php index 7c049d07..b22a7ba3 100644 --- a/src/Admin/Upgrades.php +++ b/src/Admin/Upgrades.php @@ -26,9 +26,9 @@ class Upgrades { /** * Constructor for Upgrades. * - * @return void * @since 1.3.0 * @access public + * @return void */ public function __construct() { add_action( 'init', [ $this, 'run' ] ); @@ -38,13 +38,13 @@ public function __construct() { * Register routines for upgrades. * This is intended for automatic upgrade routines having less resource intensive tasks. * + * @since 1.3.0 + * @access public * @return void * * @throws Exception * * @codeCoverageIgnore - * @since 1.3.0 - * @access public */ public function run() { $plausible_analytics_version = get_option( 'plausible_analytics_version' ); @@ -98,6 +98,10 @@ public function run() { $this->upgrade_to_254(); } + if ( version_compare( $plausible_analytics_version, '2.5.8', '<' ) ) { + $this->upgrade_to_258(); + } + // Add required upgrade routines for future versions here. } @@ -105,10 +109,10 @@ public function run() { * Upgrade routine for 1.2.5 * Cleans Custom Domain related options from database, as it was removed in this version. * - * @return void - * @codeCoverageIgnore * @since 1.2.5 * @access public + * @return void + * @codeCoverageIgnore */ public function upgrade_to_125() { $old_settings = Helpers::get_settings(); @@ -138,13 +142,12 @@ public function upgrade_to_125() { /** * Get rid of the previous "example.com" default for self_hosted_domain. * + * @since 1.2.6 * @return void * @codeCoverageIgnore - * @since 1.2.6 */ public function upgrade_to_126() { $old_settings = Helpers::get_settings(); - $new_settings = $old_settings; if ( ! empty( $old_settings['self_hosted_domain'] ) && strpos( $old_settings['self_hosted_domain'], 'example.com' ) !== false ) { Helpers::update_setting( 'self_hosted_domain', '' ); @@ -265,11 +268,11 @@ public function upgrade_to_210() { /** * If EDD is active and Ecommerce is enabled, create goals after updating the plugin. * + * @since v2.3.0 + * * @return void * * @codeCoverageIgnore because all we'd be doing is testing the Plugins API. - * @since v2.3.0 - * */ public function upgrade_to_230() { $settings = Helpers::get_settings(); @@ -367,7 +370,7 @@ public function upgrade_to_254() { return; } - // Show CE notice if self-hosted domain is set, otherwise show Cloud notice. + // Show CE notice if Self-hosted Domain is set, otherwise show Cloud notice. if ( ! empty( $self_hosted_domain ) ) { add_action( 'admin_notices', [ $this, 'show_ce_api_token_notice' ] ); @@ -377,6 +380,23 @@ public function upgrade_to_254() { add_action( 'admin_notices', [ $this, 'show_cloud_api_token_notice' ] ); } + /** + * Updates the Proxy Module if Proxy is enabled. + * + * @return void + */ + public function upgrade_to_258() { + $proxy_enabled = Helpers::proxy_enabled(); + + if ( $proxy_enabled ) { + $installer = new Module(); + + $installer->install(); + } + + update_option( 'plausible_analytics_version', '2.5.8' ); + } + /** * Display a notice to CE users that haven't entered an API token yet. * From 4c416a39aeed5e18606f197fa83a5be1ed65b0ea Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Tue, 5 May 2026 16:01:31 +0200 Subject: [PATCH 4/4] Ignore this code. --- src/Admin/Upgrades.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Admin/Upgrades.php b/src/Admin/Upgrades.php index b22a7ba3..07532d86 100644 --- a/src/Admin/Upgrades.php +++ b/src/Admin/Upgrades.php @@ -384,6 +384,8 @@ public function upgrade_to_254() { * Updates the Proxy Module if Proxy is enabled. * * @return void + * + * @codeCoverageIgnore */ public function upgrade_to_258() { $proxy_enabled = Helpers::proxy_enabled();