PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.1
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.1
2.7.1 2.7.2 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 All 141 releases
← All changes | includes/class-metasync.php +13 -17 2.7.0 → 2.7.1 View file →
@@ -161,9 +161,9 @@
161 161 // Procedural init file — not a class, must stay explicit.
162 162 if (file_exists(plugin_dir_path(dirname(__FILE__)) . 'google-index/google-index-init.php')) {
163 163 require_once plugin_dir_path(dirname(__FILE__)) . 'google-index/google-index-init.php';
164 164 } else {
165 - error_log('MetaSync Google Index: google-index-init.php not found at ' . plugin_dir_path(dirname(__FILE__)) . 'google-index/google-index-init.php');
165 + error_log('MetaSync Google Index: google-index-init.php not found at ' . plugin_dir_path(dirname(__FILE__)) . 'google-index/google-index-init.php'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets
166 166 }
167 167
168 168 // The SEO precedence resolver is referenced statically from the render
169 169 // filters, the sync layer and four admin screens. Require it explicitly
@@ -279,16 +279,12 @@
279 279 $this->loader->add_action('wp_ajax_metasync_generate_connect_url', $plugin_admin, 'generate_searchatlas_connect_url');
280 280 $this->loader->add_action('wp_ajax_metasync_check_connect_status', $plugin_admin, 'check_searchatlas_connect_status');
281 281 $this->loader->add_action('wp_ajax_metasync_reset_authentication', $plugin_admin, 'reset_searchatlas_authentication');
282 282
283 - // Auto-update filter
284 - $this->loader->add_filter('auto_update_plugin', $plugin_admin, 'control_plugin_auto_updates', 10, 2);
285 -
286 283 // Search Atlas Connect development/testing endpoints
287 284 $this->loader->add_action('wp_ajax_metasync_test_enhanced_tokens', $plugin_admin, 'test_enhanced_searchatlas_tokens');
288 285 $this->loader->add_action('wp_ajax_metasync_test_whitelabel_domain', $plugin_admin, 'test_whitelabel_domain');
289 286 $this->loader->add_action('wp_ajax_metasync_test_ajax_endpoint', $plugin_admin, 'test_searchatlas_ajax_endpoint');
290 - $this->loader->add_action('wp_ajax_metasync_simple_ajax_test', $plugin_admin, 'simple_ajax_test');
291 287
292 288
293 289 $post_meta_setting = new Metasync_Post_Meta_Settings();
294 290 $this->loader->add_action('admin_init', $post_meta_setting, 'add_post_meta_data', 2);
@@ -304,11 +300,11 @@
304 300
305 301 // SEO Health CSV export: must run on admin_init (before output).
306 302 // Cheap $_GET check avoids loading the class on every admin page.
307 303 if (
308 - isset($_GET['page'], $_GET['export'], $_GET['_wpnonce']) &&
309 - $_GET['export'] === 'csv' &&
310 - strpos($_GET['page'], '-seo-health') !== false
304 + isset($_GET['page'], $_GET['export'], $_GET['_wpnonce']) && // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- routing check, the handler verifies nonce and capability
305 + $_GET['export'] === 'csv' && // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- routing check, the handler verifies nonce and capability
306 + strpos($_GET['page'], '-seo-health') !== false // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- routing check, the handler verifies nonce and capability
311 307 ) {
312 308 $this->loader->add_action('admin_init', Metasync_SEO_Health::get_instance(), 'handle_csv_export', 1);
313 309 }
314 310 $this->loader->add_action('wp', $post_meta_setting, 'show_top_admin_bar', 9);
@@ -648,9 +644,9 @@
648 644 $original_url = $url;
649 645 foreach ($url_replacements as $production => $staging) {
650 646 if (strpos($url, $production) === 0) {
651 647 $url = str_replace($production, $staging, $url);
652 - error_log("MetaSync Endpoint Filter: Replaced {$production} with {$staging} in URL: {$original_url}");
648 + error_log("MetaSync Endpoint Filter: Replaced {$production} with {$staging} in URL: {$original_url}"); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- debug-gated, no secrets
653 649 break;
654 650 }
655 651 }
656 652
@@ -934,9 +930,9 @@
934 930 }
935 931
936 932 if (!function_exists('openssl_encrypt')) {
937 933 // OpenSSL unavailable — store plaintext rather than lose the key.
938 - error_log('MetaSync: OpenSSL is unavailable — the Search Atlas API key was stored WITHOUT encryption at rest.');
934 + error_log('MetaSync: OpenSSL is unavailable — the Search Atlas API key was stored WITHOUT encryption at rest.'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets
939 935 return $plaintext;
940 936 }
941 937
942 938 $key = self::api_key_crypto_key();
@@ -945,9 +941,9 @@
945 941 $ciphertext = openssl_encrypt($plaintext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag, '', 16);
946 942
947 943 if ($ciphertext === false) {
948 944 // Encryption failed — fall back to plaintext storage, but say so.
949 - error_log('MetaSync: API key encryption failed — the Search Atlas API key was stored WITHOUT encryption at rest.');
945 + error_log('MetaSync: API key encryption failed — the Search Atlas API key was stored WITHOUT encryption at rest.'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets
950 946 return $plaintext;
951 947 }
952 948
953 949 return self::API_KEY_ENC_PREFIX . base64_encode($iv . $tag . $ciphertext);
@@ -1154,9 +1150,9 @@
1154 1150 }
1155 1151
1156 1152 if (!function_exists('openssl_encrypt')) {
1157 1153 // OpenSSL unavailable — store plaintext rather than lose the secret.
1158 - error_log('MetaSync: OpenSSL is unavailable — a secret was stored WITHOUT encryption at rest.');
1154 + error_log('MetaSync: OpenSSL is unavailable — a secret was stored WITHOUT encryption at rest.'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets
1159 1155 return $plaintext;
1160 1156 }
1161 1157
1162 1158 $key = self::secret_crypto_key();
@@ -1165,9 +1161,9 @@
1165 1161 $ciphertext = openssl_encrypt($plaintext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag, '', 16);
1166 1162
1167 1163 if ($ciphertext === false) {
1168 1164 // Encryption failed — fall back to plaintext storage, but say so.
1169 - error_log('MetaSync: Secret encryption failed — a secret was stored WITHOUT encryption at rest.');
1165 + error_log('MetaSync: Secret encryption failed — a secret was stored WITHOUT encryption at rest.'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets
1170 1166 return $plaintext;
1171 1167 }
1172 1168
1173 1169 return self::SECRET_ENC_PREFIX . base64_encode($iv . $tag . $ciphertext);
@@ -1592,9 +1588,9 @@
1592 1588 // This could be extended to store in a dedicated log table
1593 1589
1594 1590 } catch (Exception $e) {
1595 1591 // Fallback logging if structured logging fails
1596 - error_log('MetaSync API Key Event Logging Error: ' . $e->getMessage());
1592 + error_log('MetaSync API Key Event Logging Error: ' . $e->getMessage()); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets
1597 1593 }
1598 1594 }
1599 1595
1600 1596 /**
@@ -1658,9 +1654,9 @@
1658 1654 $global_hits = get_transient($global_rate_key);
1659 1655 if ($global_hits !== false && $global_hits >= 50) {
1660 1656 // More than 50 404s per minute - stop logging to protect database
1661 1657 if ($global_hits === 50) {
1662 - error_log('MetaSync 404 Monitor: Rate limit exceeded - 50+ 404s per minute. Pausing logging.');
1658 + error_log('MetaSync 404 Monitor: Rate limit exceeded - 50+ 404s per minute. Pausing logging.'); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets
1663 1659 }
1664 1660 set_transient($global_rate_key, $global_hits + 1, 60);
1665 1661 return;
1666 1662 }
@@ -1685,9 +1681,9 @@
1685 1681 require_once plugin_dir_path(dirname(__FILE__)) . '404-monitor/class-metasync-404-monitor-database.php';
1686 1682 $db_404 = new Metasync_Error_Monitor_Database();
1687 1683
1688 1684 // Get user agent (sanitized)
1689 - $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field($_SERVER['HTTP_USER_AGENT']) : '';
1685 + $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '';
1690 1686
1691 1687 // Log the 404 error
1692 1688 $result = $db_404->update([
1693 1689 'uri' => $current_url,
@@ -1713,9 +1709,9 @@
1713 1709 $host = $_SERVER['SERVER_NAME'];
1714 1710 }
1715 1711 if (empty($host)) {
1716 1712 // Fallback to WordPress site URL if available
1717 - $host = parse_url(home_url(), PHP_URL_HOST);
1713 + $host = wp_parse_url(home_url(), PHP_URL_HOST);
1718 1714 }
1719 1715
1720 1716 // Safely get REQUEST_URI with fallback
1721 1717 $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';