Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/wpdatatables/config/config.inc.php
+++ b/wpdatatables/config/config.inc.php
@@ -9,7 +9,7 @@
// Current version
-define('WDT_CURRENT_VERSION', '6.5.1.1');
+define('WDT_CURRENT_VERSION', '6.5.1.2');
// Version when hooks are updated
define('WDT_INITIAL_LITE_VERSION', '3.4.2.16');
--- a/wpdatatables/controllers/wdt_admin.php
+++ b/wpdatatables/controllers/wdt_admin.php
@@ -669,7 +669,7 @@
$tableID = (int)$_GET['table_id'];
$tableData = WDTConfigController::loadSimpleTableConfig($tableID);
} else if (isset($_GET['table_view'])) {
- $tableData = WDTConfigController::loadTableConfig((int)$_GET['table_id'], $_GET['table_view']);
+ $tableData = WDTConfigController::loadTableConfig((int)$_GET['table_id'], sanitize_text_field(wp_unslash($_GET['table_view'])));
} else {
$tableData = WDTConfigController::loadTableConfig((int)$_GET['table_id']);
}
--- a/wpdatatables/controllers/wdt_functions.php
+++ b/wpdatatables/controllers/wdt_functions.php
@@ -319,7 +319,7 @@
$query = "SELECT COUNT(*) FROM {$wpdb->prefix}wpdatatables ORDER BY id";
$allTables = $wpdb->get_var($query);
- $wpdtPage = isset($_GET['page']) ? $_GET['page'] : '';
+ $wpdtPage = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
$installDate = get_option('wdtInstallDate');
$currentDate = date('Y-m-d');
$tempIgnoreDate = get_option('wdtTempFutureDate');
@@ -372,7 +372,7 @@
return;
}
- $wpdt_page = isset($_GET['page']) ? $_GET['page'] : '';
+ $wpdt_page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
if (strpos($wpdt_page, 'wpdatatables') === false) {
return;
}
--- a/wpdatatables/source/class.wdtbrowsechartstable.php
+++ b/wpdatatables/source/class.wdtbrowsechartstable.php
@@ -70,10 +70,11 @@
$query = "SELECT COUNT(*) FROM {$wpdb->prefix}wpdatacharts";
if (isset($_REQUEST['s'])) {
- if (is_numeric($_REQUEST['s'])){
- $query .= " WHERE id LIKE '" . sanitize_text_field($_REQUEST['s']) . "'";
+ $searchTerm = sanitize_text_field(wp_unslash($_REQUEST['s']));
+ if (is_numeric($searchTerm)){
+ $query .= $wpdb->prepare(" WHERE id LIKE %s", $searchTerm);
}else{
- $query .= " WHERE title LIKE '%" . sanitize_text_field($_REQUEST['s']) . "%'";
+ $query .= $wpdb->prepare(" WHERE title LIKE %s", '%' . $wpdb->esc_like($searchTerm) . '%');
}
}
@@ -97,10 +98,11 @@
FROM {$wpdb->prefix}wpdatacharts ";
if (isset($_REQUEST['s'])) {
- if (is_numeric($_REQUEST['s'])){
- $query .= " WHERE id LIKE '" . sanitize_text_field($_REQUEST['s']) . "'";
+ $searchTerm = sanitize_text_field(wp_unslash($_REQUEST['s']));
+ if (is_numeric($searchTerm)){
+ $query .= $wpdb->prepare(" WHERE id LIKE %s", $searchTerm);
}else{
- $query .= " WHERE title LIKE '%" . sanitize_text_field($_REQUEST['s']) . "%'";
+ $query .= $wpdb->prepare(" WHERE title LIKE %s", '%' . $wpdb->esc_like($searchTerm) . '%');
}
}
@@ -343,7 +345,7 @@
$current_url = remove_query_arg('paged', $current_url);
if (isset($_GET['orderby'])) {
- $current_orderby = $_GET['orderby'];
+ $current_orderby = sanitize_text_field(wp_unslash($_GET['orderby']));
} else {
$current_orderby = '';
}
--- a/wpdatatables/source/class.wdtbrowsetable.php
+++ b/wpdatatables/source/class.wdtbrowsetable.php
@@ -65,10 +65,11 @@
global $wpdb;
$query = "SELECT COUNT(*) FROM {$wpdb->prefix}wpdatatables";
if (isset($_REQUEST['s'])) {
- if (is_numeric($_REQUEST['s'])) {
- $query .= " WHERE id LIKE '" . sanitize_text_field($_REQUEST['s']) . "'";
+ $searchTerm = sanitize_text_field(wp_unslash($_REQUEST['s']));
+ if (is_numeric($searchTerm)) {
+ $query .= $wpdb->prepare(" WHERE id LIKE %s", $searchTerm);
} else {
- $query .= " WHERE title LIKE '%" . sanitize_text_field($_REQUEST['s']) . "%'";
+ $query .= $wpdb->prepare(" WHERE title LIKE %s", '%' . $wpdb->esc_like($searchTerm) . '%');
}
}
$count = $wpdb->get_var($query);
@@ -89,10 +90,11 @@
$query = "SELECT id, title, table_type, editable FROM {$wpdb->prefix}wpdatatables ";
if (isset($_REQUEST['s'])) {
- if (is_numeric($_REQUEST['s'])) {
- $query .= " WHERE id LIKE '" . sanitize_text_field($_REQUEST['s']) . "'";
+ $searchTerm = sanitize_text_field(wp_unslash($_REQUEST['s']));
+ if (is_numeric($searchTerm)) {
+ $query .= $wpdb->prepare(" WHERE id LIKE %s", $searchTerm);
} else {
- $query .= " WHERE title LIKE '%" . sanitize_text_field($_REQUEST['s']) . "%'";
+ $query .= $wpdb->prepare(" WHERE title LIKE %s", '%' . $wpdb->esc_like($searchTerm) . '%');
}
}
@@ -282,7 +284,7 @@
$current_url = remove_query_arg('paged', $current_url);
if (isset($_GET['orderby'])) {
- $current_orderby = $_GET['orderby'];
+ $current_orderby = sanitize_text_field(wp_unslash($_GET['orderby']));
} else {
$current_orderby = '';
}
--- a/wpdatatables/source/class.wdtpermissionslisttable.php
+++ b/wpdatatables/source/class.wdtpermissionslisttable.php
@@ -93,7 +93,7 @@
$current_url = remove_query_arg('paged', $current_url);
if (isset($_GET['orderby'])) {
- $current_orderby = $_GET['orderby'];
+ $current_orderby = sanitize_text_field(wp_unslash($_GET['orderby']));
} else {
$current_orderby = '';
}
--- a/wpdatatables/source/class.wpdatatable.php
+++ b/wpdatatables/source/class.wpdatatable.php
@@ -2543,7 +2543,7 @@
$columnIndex = 1;
// Check the search values passed from URL
if (isset($_GET['wdt_search'])) {
- $this->setDefaultSearchValue($_GET['wdt_search']);
+ $this->setDefaultSearchValue(sanitize_text_field(wp_unslash($_GET['wdt_search'])));
}
// Define all column-dependent rendering rules
@@ -2953,7 +2953,7 @@
$obj = apply_filters('wpdatatables_filter_table_description', $obj, $this->getWpId(), $this);
- return json_encode($obj, JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG);
+ return json_encode($obj, JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP);
}
--- a/wpdatatables/templates/admin/dashboard/dashboard.inc.php
+++ b/wpdatatables/templates/admin/dashboard/dashboard.inc.php
@@ -343,7 +343,8 @@
<div class="alert alert-info m-b-0" role="alert">
<i class="wpdt-icon-info-circle-full"></i>
<ul>
- <li>Added WordPress MCP integration with 17 AI agent abilities for tables, charts, data, media, settings, and system info.</li>
+ <li><strong>Security:</strong> Fixed a reflected Cross-Site Scripting (XSS) vulnerability via the <code>wdt_search</code> URL parameter.</li>
+ <li><strong>Security:</strong> Hardened input sanitization for additional URL parameters and fixed a potential SQL injection in the Browse Tables and Browse Charts search.</li>
<li>Other small bug fixes and stability improvements.</li>
</ul>
</div>
--- a/wpdatatables/templates/frontend/table_main.inc.php
+++ b/wpdatatables/templates/frontend/table_main.inc.php
@@ -19,7 +19,7 @@
?>
<?php do_action('wpdatatables_before_table', $this->getWpId()); ?>
<?php wp_nonce_field('wdtFrontendEditTableNonce', 'wdtNonceFrontendEdit'); ?>
- <input type="hidden" id="<?php echo esc_attr($this->getId()) ?>_desc" value='<?php echo $this->getJsonDescription(); ?>'/>
+ <input type="hidden" id="<?php echo esc_attr($this->getId()) ?>_desc" value='<?php echo esc_attr($this->getJsonDescription()); ?>'/>
<table id="<?php echo esc_attr($this->getId()) ?>"
class="<?php if ($this->isScrollable()) { ?>scroll<?php } ?>
--- a/wpdatatables/wpdatatables.php
+++ b/wpdatatables/wpdatatables.php
@@ -3,7 +3,7 @@
Plugin Name: wpDataTables - Tables & Table Charts
Plugin URI: https://wpdatatables.com
Description: Create responsive, sortable tables & charts from Excel, CSV or PHP. Add tables & charts to any post in minutes with DataTables.
-Version: 6.5.1.1
+Version: 6.5.1.2
Author: Melograno Ventures
Author URI: https://melograno.io
Text Domain: wpdatatables