Skip to content

Commit b397652

Browse files
committed
Improved: hardened Proxy Speed Module, to make sure it doesn't disable plugins on non-proxy requests.
1 parent 8c36f00 commit b397652

1 file changed

Lines changed: 33 additions & 15 deletions

File tree

mu-plugin/plausible-proxy-speed-module.php

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,26 @@
44
* Description: Speeds up Plausible Analytics' proxy for avoiding ad blockers.
55
* Plugin URI: https://plausible.io
66
* Author: Plausible HQ
7-
* Version: 1.0.0
7+
* Version: 1.0.1
88
* Author URI: https://plausible.io
99
*
1010
* Text Domain: plausible-analytics
1111
*/
1212

1313
class PlausibleProxySpeed {
1414
/**
15-
* Is current request a request to our proxy?
15+
* Is the current request a request to our proxy?
1616
*
1717
* @var bool
1818
*/
19-
private $is_proxy_request = false;
19+
private $is_proxy_request;
2020

2121
/**
2222
* Current request URI.
2323
*
2424
* @var string
2525
*/
26-
private $request_uri = '';
26+
private $request_uri;
2727

2828
/**
2929
* Build properties.
@@ -38,27 +38,44 @@ public function __construct() {
3838
}
3939

4040
/**
41-
* Helper method to retrieve Request URI. Checks several globals.
41+
* Helper method to retrieve Request URI.
4242
*
43-
* @return mixed
43+
* @return string
4444
*/
4545
private function get_request_uri() {
46-
return $_SERVER[ 'REQUEST_URI' ];
46+
return $_SERVER['REQUEST_URI'] ?? '';
4747
}
4848

4949
/**
50-
* Check if current request is a proxy request.
50+
* Check if the current request is a proxy request.
51+
*
52+
* The namespace must appear as a path segment under the REST prefix
53+
* (e.g. /wp-json/<namespace>[/...]). Substring matches in query
54+
* strings, fragments, or unrelated path segments are rejected.
5155
*
5256
* @return bool
5357
*/
5458
private function is_proxy_request() {
55-
$namespace = get_option( 'plausible_analytics_proxy_resources' )[ 'namespace' ] ?? '';
59+
$namespace = get_option( 'plausible_analytics_proxy_resources' )['namespace'] ?? '';
5660

5761
if ( ! $namespace ) {
5862
return false;
5963
}
6064

61-
return strpos( $this->request_uri, $namespace ) !== false;
65+
$path = parse_url( $this->request_uri, PHP_URL_PATH );
66+
67+
if ( ! is_string( $path ) || $path === '' ) {
68+
return false;
69+
}
70+
71+
$rest_prefix = function_exists( 'rest_get_url_prefix' )
72+
? trim( rest_get_url_prefix(), '/' )
73+
: 'wp-json';
74+
75+
$expected = '/' . $rest_prefix . '/' . trim( $namespace, '/' );
76+
77+
return $path === $expected
78+
|| str_starts_with( $path, $expected . '/' );
6279
}
6380

6481
/**
@@ -73,6 +90,10 @@ private function init() {
7390
/**
7491
* Filter the list of active plugins for custom endpoint requests.
7592
*
93+
* Uses basename() exact-match comparison instead of strpos(), so a
94+
* plugin file path can only match if its filename is exactly in the
95+
* allowlist.
96+
*
7697
* @param array $active_plugins The list of active plugins.
7798
*
7899
* @return array The filtered list of active plugins.
@@ -86,11 +107,8 @@ public function filter_active_plugins( $active_plugins ) {
86107
$filtered_plugins = [];
87108

88109
foreach ( $active_plugins as $plugin ) {
89-
foreach ( $allowed_plugin_files as $allowed_plugin_file ) {
90-
if ( strpos( $plugin, $allowed_plugin_file ) !== false ) {
91-
$filtered_plugins[] = $plugin;
92-
break;
93-
}
110+
if ( in_array( basename( $plugin ), $allowed_plugin_files, true ) ) {
111+
$filtered_plugins[] = $plugin;
94112
}
95113
}
96114

0 commit comments

Comments
 (0)