Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/seo-by-rank-math/includes/abilities/link-genius/class-link-report-runner.php
+++ b/seo-by-rank-math/includes/abilities/link-genius/class-link-report-runner.php
@@ -81,7 +81,7 @@
if ( ! isset( $result['audit'] ) ) {
$result['upgrade'] = [
- 'message' => esc_html__( 'Upgrade to Rank Math PRO to unlock broken link detection, redirect chain analysis, and HTTP status distribution from the Link Genius audit.', 'seo-by-rank-math' ),
+ 'message' => esc_html__( 'Upgrade to Rank Math PRO to unlock broken link detection, redirect chain analysis, and HTTP status distribution from the AI Link Genius audit.', 'seo-by-rank-math' ),
'url' => 'https://rankmath.com/pricing/',
];
}
--- a/seo-by-rank-math/includes/abilities/link-genius/class-subscriber.php
+++ b/seo-by-rank-math/includes/abilities/link-genius/class-subscriber.php
@@ -63,7 +63,7 @@
wp_register_ability_category(
self::CATEGORY_SLUG,
[
- 'label' => esc_html__( 'Link Genius', 'seo-by-rank-math' ),
+ 'label' => esc_html__( 'AI Link Genius', 'seo-by-rank-math' ),
'description' => esc_html__( 'Abilities to retrieve and analyse internal and external link data for posts.', 'seo-by-rank-math' ),
]
);
--- a/seo-by-rank-math/includes/admin/class-admin-menu.php
+++ b/seo-by-rank-math/includes/admin/class-admin-menu.php
@@ -15,7 +15,6 @@
use RankMathHelpersParam;
use RankMathRunner;
use RankMathTraitsHooker;
-use RankMathTraitsAjax;
use RankMathAdminPage;
defined( 'ABSPATH' ) || exit;
@@ -28,7 +27,6 @@
class Admin_Menu implements Runner {
use Hooker;
- use Ajax;
/**
* Register hooks.
@@ -37,7 +35,6 @@
$this->action( 'init', 'register_pages' );
$this->action( 'admin_menu', 'fix_admin_menu', 999 );
$this->action( 'admin_head', 'icon_css' );
- $this->ajax( 'remove_offer_page', 'remove_offer_page' );
}
/**
@@ -163,18 +160,8 @@
<script type="text/javascript">
// Open RM KB menu link in the new tab.
jQuery( document ).ready( function( $ ) {
- $( "ul#adminmenu a[href$='<?php KB::the( 'knowledgebase', 'Sidebar Help Link' ); ?>']" ).attr( 'target', '_blank' );
- $( "ul#adminmenu a[href$='<?php KB::the( 'offer', 'Offer Menu Item' ); ?>']" ).attr( 'target', '_blank' ).on( 'click', function() {
- $( this ).remove()
- $.ajax( {
- url: window.ajaxurl,
- type: 'POST',
- data: {
- action: 'rank_math_remove_offer_page',
- security: rankMath.security,
- },
- } )
- } );
+ $( "ul#adminmenu a[href$='<?php KB::the( 'knowledgebase', 'Sidebar Help Link' ); ?>']" ).attr( 'target', '_blank' )
+ $( "ul#adminmenu a[href$='<?php echo esc_url_raw( $this->get_offer_link() ); ?>']" ).attr( 'target', '_blank' )
} );
</script>
<style>
@@ -193,15 +180,15 @@
fill-rule: evenodd;
fill: #00b9eb;
}
- #toplevel_page_rank-math:not(.wp-has-submenu) {
+ #adminmenu #toplevel_page_rank-math:not(.wp-has-submenu) {
display: none;
}
.multisite.network-admin #toplevel_page_rank-math {
display: block;
}
- #toplevel_page_rank-math a[href$='<?php KB::the( 'offer', 'Offer Menu Item' ); ?>'],
- #toplevel_page_rank-math a[href$='<?php KB::the( 'offer', 'Offer Menu Item' ); ?>']:hover,
- #toplevel_page_rank-math a[href$='<?php KB::the( 'offer', 'Offer Menu Item' ); ?>']:focus {
+ #adminmenu #toplevel_page_rank-math a[href$='<?php echo esc_url_raw( $this->get_offer_link() ); ?>'],
+ #adminmenu #toplevel_page_rank-math a[href$='<?php echo esc_url_raw( $this->get_offer_link() ); ?>']:hover,
+ #adminmenu #toplevel_page_rank-math a[href$='<?php echo esc_url_raw( $this->get_offer_link() ); ?>']:focus {
background-color: #10AC84;
color: #fff;
}
@@ -236,16 +223,14 @@
return;
}
- $submenu['rank-math'][] = [ current( $offer ) . ' ', 'manage_options', KB::get( 'offer', 'Offer Menu Item' ) ];
+ $submenu['rank-math'][] = [ current( $offer ) . ' ', 'manage_options', $this->get_offer_link() ];
}
/**
- * Ajax handler callback to store active offer so it doesn't show up again on the site.
+ * Get the offer link.
*/
- public function remove_offer_page() {
- check_ajax_referer( 'rank-math-ajax-nonce', 'security' );
- $offer = $this->get_active_offer();
- set_site_transient( 'rank_math_active_offer', key( $offer ) );
+ private function get_offer_link() {
+ return KB::get( 'pro', 'upgrade-dashboard-notifications-menu' );
}
/**
@@ -261,44 +246,45 @@
$current_date = new DateTime( 'now', $timezone );
$dates = [
'halloween' => [
- 'start' => '2025-10-29',
- 'end' => '2025-11-05',
+ 'start' => '2026-10-28',
+ 'end' => '2026-11-03',
'text' => esc_html__( 'Halloween Sale', 'seo-by-rank-math' ),
],
'anniversary' => [
- 'start' => '2025-11-05',
- 'end' => '2025-11-12',
+ 'start' => '2026-11-04',
+ 'end' => '2026-11-10',
'text' => esc_html__( 'Anniversary Sale', 'seo-by-rank-math' ),
],
'black-friday' => [
- 'start' => '2025-11-12',
- 'end' => '2025-11-29',
+ 'start' => '2026-11-11',
+ 'end' => '2026-11-27',
'text' => esc_html__( 'Black Friday Sale', 'seo-by-rank-math' ),
],
'cyber-monday' => [
- 'start' => '2025-11-29',
- 'end' => '2025-12-03',
+ 'start' => '2026-11-28',
+ 'end' => '2026-12-02',
'text' => esc_html__( 'Cyber Monday Sale', 'seo-by-rank-math' ),
],
'christmas' => [
- 'start' => '2025-12-24',
- 'end' => '2025-12-31',
+ 'start' => '2026-12-24',
+ 'end' => '2026-12-31',
'text' => esc_html__( 'Christmas Sale', 'seo-by-rank-math' ),
],
'new-year' => [
- 'start' => '2025-12-31',
- 'end' => '2026-01-07',
+ 'start' => '2027-01-01',
+ 'end' => '2027-01-07',
'text' => esc_html__( 'New Year Sale', 'seo-by-rank-math' ),
],
];
- $stored_offer = get_site_transient( 'rank_math_active_offer' );
- $active_offer = '';
+ $active_offer = [
+ 'unlock-pro' => esc_html__( 'Unlock PRO', 'seo-by-rank-math' ),
+ ];
foreach ( $dates as $key => $date ) {
$start_date = new DateTime( $date['start'] . ' 16:00:00', $timezone );
$end_date = new DateTime( $date['end'] . ' 16:00:00', $timezone );
- if ( $stored_offer !== $key && $current_date >= $start_date && $current_date <= $end_date ) {
+ if ( $current_date >= $start_date && $current_date <= $end_date ) {
$active_offer = [ $key => $date['text'] ];
break;
}
--- a/seo-by-rank-math/includes/module/class-manager.php
+++ b/seo-by-rank-math/includes/module/class-manager.php
@@ -162,7 +162,7 @@
];
$modules['link-genius'] = [
- 'title' => esc_html__( 'Link Genius', 'seo-by-rank-math' ),
+ 'title' => esc_html__( 'AI Link Genius', 'seo-by-rank-math' ),
'desc' => esc_html__( 'An advanced internal linking tool that analyzes your posts, tracks link data, highlights opportunities, and offers detailed report.', 'seo-by-rank-math' ),
'icon' => 'link',
'probadge' => true,
@@ -569,7 +569,7 @@
</ul>
</header>
<div class="status wp-clearfix">
- <button class="button button-secondary"><?php esc_html_e( 'Buy', 'seo-by-rank-math' ); ?></button>
+ <button class="button button-secondary"><?php esc_html_e( 'Buy Now', 'seo-by-rank-math' ); ?></button>
</div>
</a>
</div>
--- a/seo-by-rank-math/includes/modules/analytics/class-ajax.php
+++ b/seo-by-rank-math/includes/modules/analytics/class-ajax.php
@@ -276,6 +276,9 @@
$this->has_cap_ajax( 'analytics' );
WorkflowWorkflow::kill_workflows();
+ // Clear fetching state immediately so the UI reflects the cancellation on reload.
+ update_option( 'rank_math_analytics_first_fetch', 'hidden' );
+
$this->success( esc_html__( 'Data fetching cancelled.', 'seo-by-rank-math' ) );
}
@@ -300,6 +303,10 @@
delete_option( 'rank_math_analytics_installed' );
}
delete_option( 'rank_math_analytics_last_single_action_schedule_time' );
+
+ // Set fetching state synchronously so a reload doesn't race the async workflow.
+ update_option( 'rank_math_analytics_first_fetch', 'fetching' );
+
// Start fetching data.
foreach ( [ 'console', 'analytics', 'adsense' ] as $action ) {
WorkflowWorkflow::do_workflow(
--- a/seo-by-rank-math/includes/modules/analytics/class-db.php
+++ b/seo-by-rank-math/includes/modules/analytics/class-db.php
@@ -453,13 +453,13 @@
$host = Helper::get_home_url();
$url = str_replace( $host, '', $url );
- // Remove ASCII domain.
- $host_ascii = idn_to_ascii( $host );
+ // Remove ASCII domain, guarded since ext-intl may be unavailable.
+ $host_ascii = function_exists( 'idn_to_ascii' ) ? idn_to_ascii( $host ) : $host;
$url = str_replace( $host_ascii, '', $url );
$url = preg_replace( '#^https?://(www.)?#i', '', $url );
- return $url;
+ return apply_filters( 'rank_math/analytics/get_page', $url );
}
/**
--- a/seo-by-rank-math/includes/modules/analytics/views/email-reports/header-after.php
+++ b/seo-by-rank-math/includes/modules/analytics/views/email-reports/header-after.php
@@ -11,21 +11,21 @@
defined( 'ABSPATH' ) || exit;
?>
-<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="report-info">
- <tr>
- <td>
- <h1><?php esc_html_e( 'SEO Report of Your Website', 'seo-by-rank-math' ); ?></h1>
- <h2 class="report-date">###START_DATE### - ###END_DATE###</h2>
- <a href="###SITE_URL###" target="_blank" class="site-url">###SITE_URL_SIMPLE###</a>
- </td>
- <td class="full-report-link">
- <a href="###REPORT_URL###" target="_blank" class="full-report-link">
+<div class="report-info">
+ <div class="report-info-row">
+ <h1><?php esc_html_e( 'SEO Report of Your Website', 'seo-by-rank-math' ); ?></h1>
+ <a href="###SITE_URL###" target="_blank" class="site-url">###SITE_URL_SIMPLE###</a>
+ </div>
+ <div class="report-info-row report-meta-row">
+ <h2 class="report-date">###START_DATE### - ###END_DATE###</h2>
+ <div class="full-report-link">
+ <a href="###REPORT_URL###" target="_blank">
<?php esc_html_e( 'FULL REPORT', 'seo-by-rank-math' ); ?>
<?php $this->image( 'report-icon-external.png', 12, 12, __( 'External Link Icon', 'seo-by-rank-math' ) ); ?>
</a>
- </td>
- </tr>
-</table>
+ </div>
+ </div>
+</div>
<?php if ( $this->get_variable( 'stats_invalid_data' ) ) { ?>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="report-error">
--- a/seo-by-rank-math/includes/modules/analytics/views/email-reports/style.php
+++ b/seo-by-rank-math/includes/modules/analytics/views/email-reports/style.php
@@ -200,7 +200,7 @@
}
h2.report-date {
- margin: 25px 0 4px;
+ margin: 0;
font-size: 18px;
}
@@ -210,10 +210,26 @@
font-size: 15px;
}
+ .report-info {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ }
+
+ .report-info-row {
+ width: 100%;
+ }
+
+ .report-meta-row {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ margin: 25px 0 4px;
+ }
+
.full-report-link {
- vertical-align: bottom;
text-align: right;
- width: 110px;
}
.full-report-link a {
--- a/seo-by-rank-math/includes/modules/links/Admin/class-admin.php
+++ b/seo-by-rank-math/includes/modules/links/Admin/class-admin.php
@@ -48,11 +48,11 @@
public function register_admin_page() {
new Page(
'rank-math-links-page',
- esc_html__( 'Link Genius', 'seo-by-rank-math' ),
+ esc_html__( 'AI Link Genius', 'seo-by-rank-math' ),
[
'position' => 4,
'parent' => 'rank-math',
- 'menu_title' => esc_html__( 'Link Genius', 'seo-by-rank-math' ),
+ 'menu_title' => esc_html__( 'AI Link Genius', 'seo-by-rank-math' ),
'capability' => 'rank_math_link_builder',
'render' => function () {
echo '<div id="rank-math-links-page-container"></div>';
--- a/seo-by-rank-math/includes/modules/llms/class-llms-txt.php
+++ b/seo-by-rank-math/includes/modules/llms/class-llms-txt.php
@@ -157,8 +157,11 @@
$site_desc = Helper::get_settings( 'titles.organization_description', get_bloginfo( 'description' ) );
$site_title .= $site_desc ? ': ' . $site_desc : '';
- $this->output_line( 'Generated by Rank Math SEO, this is an llms.txt file designed to help LLMs better understand and index this website.' );
- $this->output_line( '' );
+ if ( ! $this->do_filter( 'llms_txt/remove_credit', false ) ) {
+ $this->output_line( 'Generated by Rank Math SEO, this is an llms.txt file designed to help LLMs better understand and index this website.' );
+ $this->output_line( '' );
+ }
+
$this->output_line( '# ' . esc_html( $site_title ) );
if ( ! Helper::is_module_active( 'sitemap' ) ) {
--- a/seo-by-rank-math/includes/modules/redirections/class-debugger.php
+++ b/seo-by-rank-math/includes/modules/redirections/class-debugger.php
@@ -125,7 +125,7 @@
setTimeout( updateTimer, 1000 );
} else {
document.getElementById( 'redirection-timer-counter' ).textContent = redirectTimer;
- window.location.href = '<?php echo esc_url_raw( $this->args['redirect_to'] ); ?>';
+ window.location.href = <?php echo wp_json_encode( esc_url_raw( $this->args['redirect_to'] ) ); ?>;
}
}
--- a/seo-by-rank-math/includes/modules/woocommerce/class-permalink-watcher.php
+++ b/seo-by-rank-math/includes/modules/woocommerce/class-permalink-watcher.php
@@ -61,6 +61,13 @@
private $remove_parent_slugs;
/**
+ * Whether a rewrite rules flush has already been scheduled for shutdown.
+ *
+ * @var bool
+ */
+ private $flush_scheduled = false;
+
+ /**
* The Constructor.
*/
public function __construct() {
@@ -83,12 +90,27 @@
}
/**
- * Flush rewrite rules (soft flush).
+ * Schedule a soft rewrite rules flush at shutdown.
+ *
+ * Deferred to avoid WPML's temporary get_terms filter limiting rewrite rules
+ * to the current language, which can cause 404s for other languages.
+ *
+ * A class property prevents duplicate closure callbacks.
*
* @return void
*/
public function flush_rules() {
- flush_rewrite_rules( false );
+ if ( $this->flush_scheduled ) {
+ return;
+ }
+
+ $this->flush_scheduled = true;
+ add_action(
+ 'shutdown',
+ function () {
+ flush_rewrite_rules( false );
+ }
+ );
}
/**
--- a/seo-by-rank-math/rank-math.php
+++ b/seo-by-rank-math/rank-math.php
@@ -9,7 +9,7 @@
*
* @wordpress-plugin
* Plugin Name: Rank Math SEO
- * Version: 1.0.274.1
+ * Version: 1.0.275
* Plugin URI: https://rankmath.com/
* Description: Rank Math SEO is the Best WordPress SEO plugin with the features of many SEO and AI SEO tools in a single package to help multiply your SEO traffic.
* Author: Rank Math SEO
@@ -34,7 +34,7 @@
*
* @var string
*/
- public $version = '1.0.274.1';
+ public $version = '1.0.275';
/**
* Rank Math database version.
@@ -460,11 +460,17 @@
];
}
+ $plugin_links = [];
foreach ( $options as $link => $label ) {
$plugin_links[] = '<a href="' . RankMathHelper::get_admin_url( $link ) . '">' . esc_html( $label ) . '</a>';
}
- return array_merge( $links, $plugin_links );
+ $pro_links = [];
+ if ( ! defined( 'RANK_MATH_PRO_FILE' ) ) {
+ $pro_links[] = '<a href="' . esc_url( RankMathKB::get( 'pro', 'upgrade-plugins-screen-link' ) ) . '" style="color: #10AC84; font-weight: 600;" target="_blank">' . esc_html__( 'Unlock PRO', 'seo-by-rank-math' ) . '</a>';
+ }
+
+ return array_merge( $pro_links, $links, $plugin_links );
}
/**
--- a/seo-by-rank-math/vendor/autoload.php
+++ b/seo-by-rank-math/vendor/autoload.php
@@ -22,4 +22,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInit8d167c330be88fc6ab56339065b33284::getLoader();
+return ComposerAutoloaderInit398526c2083ae696eae4a2a9be291494::getLoader();
--- a/seo-by-rank-math/vendor/composer/autoload_real.php
+++ b/seo-by-rank-math/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit8d167c330be88fc6ab56339065b33284
+class ComposerAutoloaderInit398526c2083ae696eae4a2a9be291494
{
private static $loader;
@@ -24,18 +24,18 @@
require __DIR__ . '/platform_check.php';
- spl_autoload_register(array('ComposerAutoloaderInit8d167c330be88fc6ab56339065b33284', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit398526c2083ae696eae4a2a9be291494', 'loadClassLoader'), true, true);
self::$loader = $loader = new ComposerAutoloadClassLoader(dirname(__DIR__));
- spl_autoload_unregister(array('ComposerAutoloaderInit8d167c330be88fc6ab56339065b33284', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit398526c2083ae696eae4a2a9be291494', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- call_user_func(ComposerAutoloadComposerStaticInit8d167c330be88fc6ab56339065b33284::getInitializer($loader));
+ call_user_func(ComposerAutoloadComposerStaticInit398526c2083ae696eae4a2a9be291494::getInitializer($loader));
$loader->register(true);
- $includeFiles = ComposerAutoloadComposerStaticInit8d167c330be88fc6ab56339065b33284::$files;
+ $includeFiles = ComposerAutoloadComposerStaticInit398526c2083ae696eae4a2a9be291494::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
- composerRequire8d167c330be88fc6ab56339065b33284($fileIdentifier, $file);
+ composerRequire398526c2083ae696eae4a2a9be291494($fileIdentifier, $file);
}
return $loader;
@@ -47,7 +47,7 @@
* @param string $file
* @return void
*/
-function composerRequire8d167c330be88fc6ab56339065b33284($fileIdentifier, $file)
+function composerRequire398526c2083ae696eae4a2a9be291494($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
--- a/seo-by-rank-math/vendor/composer/autoload_static.php
+++ b/seo-by-rank-math/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
namespace ComposerAutoload;
-class ComposerStaticInit8d167c330be88fc6ab56339065b33284
+class ComposerStaticInit398526c2083ae696eae4a2a9be291494
{
public static $files = array (
'da5f6548f070d3d306f90eee42dd5de6' => __DIR__ . '/..' . '/donatj/phpuseragentparser/src/UserAgentParser.php',
@@ -493,9 +493,9 @@
public static function getInitializer(ClassLoader $loader)
{
return Closure::bind(function () use ($loader) {
- $loader->prefixLengthsPsr4 = ComposerStaticInit8d167c330be88fc6ab56339065b33284::$prefixLengthsPsr4;
- $loader->prefixDirsPsr4 = ComposerStaticInit8d167c330be88fc6ab56339065b33284::$prefixDirsPsr4;
- $loader->classMap = ComposerStaticInit8d167c330be88fc6ab56339065b33284::$classMap;
+ $loader->prefixLengthsPsr4 = ComposerStaticInit398526c2083ae696eae4a2a9be291494::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit398526c2083ae696eae4a2a9be291494::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInit398526c2083ae696eae4a2a9be291494::$classMap;
}, null, ClassLoader::class);
}
--- a/seo-by-rank-math/vendor/composer/installed.php
+++ b/seo-by-rank-math/vendor/composer/installed.php
@@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'rankmath/seo-by-rank-math',
- 'pretty_version' => 'v1.0.274.1',
- 'version' => '1.0.274.1',
- 'reference' => '9b45f41985e405903ddb2572a9084c1e9798763c',
+ 'pretty_version' => 'v1.0.275',
+ 'version' => '1.0.275.0',
+ 'reference' => '8c27c8e0d21755e932dd99e005bb3e73d2006ce1',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -38,9 +38,9 @@
'dev_requirement' => false,
),
'rankmath/seo-by-rank-math' => array(
- 'pretty_version' => 'v1.0.274.1',
- 'version' => '1.0.274.1',
- 'reference' => '9b45f41985e405903ddb2572a9084c1e9798763c',
+ 'pretty_version' => 'v1.0.275',
+ 'version' => '1.0.275.0',
+ 'reference' => '8c27c8e0d21755e932dd99e005bb3e73d2006ce1',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),