PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.0
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.0
2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 2.6.4 2.6.3 All 139 releases
← All changes | includes/class-metasync-redirections-admin.php +11 -3 2.6.212.7.0 View file →
@@ -187,8 +187,14 @@
187 187 if (empty($trimmed_dest)) {
188 188 $validation_errors[] = 'Destination URL is required for this redirect type.';
189 189 } elseif (!$this->is_valid_url($trimmed_dest)) {
190 190 $validation_errors[] = 'Invalid destination URL format. URLs should start with / for relative paths or be complete URLs.';
191 + } elseif (!Metasync_Redirection_Validator::is_safe_destination_syntax($trimmed_dest)) {
192 + // Browsers treat backslashes as path separators, so '/\evil.com'
193 + // passes wp_validate_redirect yet navigates off-site; a leading
194 + // '//' is a protocol-relative host. Neither is a valid internal
195 + // destination regardless of the external-redirects setting.
196 + $validation_errors[] = 'Destination URL contains invalid characters.';
191 197 } elseif (!get_option('metasync_allow_external_redirects', 0) && wp_validate_redirect($trimmed_dest, '') !== $trimmed_dest) {
192 198 $validation_errors[] = 'Destination URL must point to this site. External redirect destinations are not allowed. Enable "Allow External Redirects" in the Redirections settings to permit off-site redirects.';
193 199 }
194 200 }
@@ -234,12 +240,13 @@
234 240 $this->safe_redirect(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-redirections'));
235 241 return;
236 242 }
237 243
238 - // Reject patterns with nested quantifiers that could cause ReDoS
244 + // Reject patterns with nested quantification that could cause ReDoS,
245 + // including alternation blowup ('((a|a)*)*') the older guard missed.
239 246 $raw_check = preg_replace('/^\S(.*)\S[a-zA-Z]*$/', '$1', $regex_pattern);
240 - if (preg_match('/(\([^)]*[+*][^)]*\))[+*?{]|(\[[^\]]*\])[+*][+*?{]/', $raw_check)) {
241 - set_transient('metasync_redirection_error_' . $uid, 'Regex pattern contains potentially unsafe nested quantifiers.', 45);
247 + if (!Metasync_Redirection_Validator::is_regex_safe($raw_check)) {
248 + set_transient('metasync_redirection_error_' . $uid, 'Regex pattern is too long or contains potentially unsafe nested quantifiers (including nested alternation).', 45);
242 249 $this->safe_redirect(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-redirections'));
243 250 return;
244 251 }
245 252
@@ -272,8 +279,9 @@
272 279
273 280 // Loop detection: refuse to persist a chain that would resolve back to any source
274 281 if (!in_array($redirect_type, [410, 451])) {
275 282 require_once dirname(__FILE__, 2) . '/redirections/class-metasync-redirection.php';
283 + require_once dirname(__FILE__, 2) . '/redirections/class-metasync-redirection-validator.php';
276 284 $redirection_helper = new Metasync_Redirection($this->db_redirection);
277 285 foreach (array_keys($sources_from) as $source_url) {
278 286 $loop_error = $redirection_helper->validate_no_loop($source_url, $destination_url);
279 287 if ($loop_error !== null) {