Prismatic <= 3.7.3 - Unauthenticated Stored Cross-Site Scripting via 'prismatic_encoded' Pseudo-Shortcode
Description
The Prismatic plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'prismatic_encoded' pseudo-shortcode in all versions up to, and including, 3.7.3. This is due to insufficient input sanitization and output escaping on user-supplied attributes within the 'prismatic_decode' function. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page by submitting a comment containing a crafted 'prismatic_encoded' pseudo-shortcode.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
What Changed in the Fix
Changes introduced in v3.7.4
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-3876 ## 1. Vulnerability Summary The **Prismatic** plugin for WordPress (versions <= 3.7.3) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the `prismatic_decode` function within `inc/prismatic-core.php`. This function proc…
Show full research plan
Exploitation Research Plan - CVE-2026-3876
1. Vulnerability Summary
The Prismatic plugin for WordPress (versions <= 3.7.3) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists in the prismatic_decode function within inc/prismatic-core.php. This function processes a "pseudo-shortcode" [prismatic_encoded] used by the plugin to handle code blocks.
The plugin fails to adequately sanitize the attributes provided within this pseudo-shortcode. While it attempts to use a regex whitelist to sanitize attributes, the whitelist is overly permissive, allowing attributes like onmouseover, onfocus, and values containing window.location, window.name, and document. Because the plugin hooks into the comment_text filter at a very late priority (99), it processes these pseudo-shortcodes after WordPress's standard security filters (like wp_filter_kses) have already run, allowing unauthenticated attackers to bypass comment sanitization.
2. Attack Vector Analysis
- Endpoint:
wp-comments-post.php(Standard WordPress comment submission). - Vulnerable Hook:
comment_textfilter. - Payload Parameter:
comment. - Authentication Level: Unauthenticated (if comments are open to the public).
- Preconditions:
- The Prismatic plugin must be active.
- Comments must be enabled on
Summary
The Prismatic plugin for WordPress is vulnerable to unauthenticated Stored Cross-Site Scripting (XSS) via its custom '[prismatic_encoded]' pseudo-shortcode. This occurs because the plugin uses an overly permissive regular expression to sanitize shortcode attributes and fails to properly escape them before outputting them within <code> tags, allowing attackers to inject malicious JavaScript event handlers.
Vulnerable Code
// inc/prismatic-core.php (line 92 in version 3.7.3) function prismatic_decode($text) { if (!is_string($text)) return $text; $output = ''; $split = preg_split("/(\\[prismatic_encoded.*\\].*\\[\\/prismatic_encoded\\])/Us", $text, -1, PREG_SPLIT_DELIM_CAPTURE); $count = count($split); for ($i = 0; $i < $count; $i++) { $content = $split[$i]; if (preg_match("/^\\[prismatic_encoded(.*)\\](.*)\\[\\/prismatic_encoded\\]/Us", $content, $code)) { $atts = str_replace("%%", "\"", $code[1]); $content = base64_decode($code[2]); $content = preg_replace("/\r/", "", $content); $content = preg_replace("/^\s*?\n/", "\n", $content); $atts = preg_replace('/[^a-z0-9\-\_\s\"\.\,\=]/i', '', $atts); $content = '<code'. $atts .'>'. esc_html($content) .'</code>'; } $output .= $content; } return $output; }
Security Fix
@@ -92,6 +92,14 @@ function prismatic_decode($text) { + global $prismatic_options_general; + + $options = $prismatic_options_general; + + $library = isset($options['library']) ? $options['library'] : null; + + // + if (!is_string($text)) return $text; $output = ''; @@ -112,9 +120,27 @@ $content = preg_replace("/^\s*?\n/", "\n", $content); - $atts = preg_replace('/[^a-z0-9\-\_\s\"\.\,\=]/i', '', $atts); + // + + $code = prismatic_parse_get_doc($atts); + + if ($library === 'prism') { + + $class = prismatic_parse_prism($code); + + } elseif ($library === 'highlight') { + + $class = prismatic_parse_highlight($code); + + } else { + + $class = ''; + + } + + $data_line = prismatic_parse_prism_addons($code); - $content = '<code'. $atts .'>'. esc_html($content) .'</code>'; + $content = '<code class="'. esc_attr($class) .'" data-line="'. esc_attr($data_line) .'">'. esc_html($content) .'</code>'; }
Exploit Outline
1. **Identify Vulnerable Hook**: The plugin registers `prismatic_decode` on the `comment_text` filter with a high priority (99), meaning it runs after standard WordPress comment sanitization. 2. **Craft Payload**: Create a comment containing the `[prismatic_encoded]` pseudo-shortcode. The attribute section of the shortcode can include event handlers because the sanitization regex `/[^a-z0-9\-\_\s\"\.\,\=]/i` permits spaces, equals signs, and quotes. 3. **Payload Example**: `[prismatic_encoded onmouseover="alert(document.domain)" class="language-javascript"]Y29uc29sZS5sb2coMSk=[/prismatic_encoded]` (Note: the content between tags must be Base64 encoded). 4. **Submit Comment**: As an unauthenticated user, post the crafted comment to a page where comments are enabled. 5. **Execution**: When a user or administrator views the comment, the plugin renders the raw `onmouseover` attribute inside a `<code>` tag. Hovering over the code block triggers the JavaScript.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.