CVE-2025-47500

Stackable <= 3.19.5 - Authenticated (Author+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
3.19.6
Patched in
26d
Time to patch

Description

The Stackable plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.19.5 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with author-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<=3.19.5
PublishedJanuary 7, 2026
Last updatedFebruary 2, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot fulfill this request. I am prohibited from generating detailed, actionable research plans or proof-of-concept instructions for the exploitation of specific security vulnerabilities. I can, however, explain the general mechanics of Stored Cross-Site Scripting (XSS) within the WordPress block…

Show full research plan

I cannot fulfill this request. I am prohibited from generating detailed, actionable research plans or proof-of-concept instructions for the exploitation of specific security vulnerabilities. I can, however, explain the general mechanics of Stored Cross-Site Scripting (XSS) within the WordPress block editor environment and the defensive measures used to prevent it.

Stored XSS in Gutenberg Blocks

Stored XSS in the context of WordPress Gutenberg blocks typically occurs when a block's attributes—the data that defines its settings and content—are not properly sanitized before being saved to the database or are not correctly escaped when rendered in the editor or on the frontend.

General Mechanism

  1. Attribute Definition: Blocks define attributes (e.g., content, url, id, customStyles) in their block.json or registerBlockType JavaScript configuration.
  2. Input and Persistence: When an authorized user (such as an Author) adds or edits a block, the editor sends a request to the WordPress REST API (e.g., POST /wp-json/wp/v2/posts/{id}) containing the block's data. WordPress stores this in the post_content field of the wp_posts table, often as JSON-like metadata within HTML comments.
  3. Insecure Sanitization: If the plugin does not use server-side sanitization functions (like sanitize_text_field or wp_kses) on these attributes before they are saved, malicious scripts can be included in the stored content.
  4. Insecure Output: When the post is viewed, the block is rendered. If the rendering logic (whether in a PHP render_callback for dynamic blocks or the JavaScript save function for static blocks) does not use context-aware escaping (like esc_attr for attributes or esc_html for content), the browser executes the stored script.

Defensive Best Practices

To prevent these vulnerabilities, developers should follow the security guidelines provided in the WordPress Plugin Handbook:

  • Server-Side Sanitization: Always validate and sanitize all block attributes on the server before they are saved to the database, especially when using the REST API.
  • Context-Aware Escaping: Use the appropriate WordPress escaping functions for every piece of data rendered in the browser:
    • esc_html() for data inside HTML tags.
    • esc_attr() for data inside HTML attributes.
    • esc_url() for URLs in href or src attributes.
    • wp_kses() or wp_kses_post() when specific HTML tags must be allowed.
  • Capability Checks: Ensure that only users with the appropriate permissions can modify sensitive block attributes.
  • Nonce Verification: Verify WordPress nonces for all REST API and AJAX requests to protect against Cross-Site Request Forgery (CSRF).

For further learning on WordPress security, you can explore resources like the OWASP Top 10 or the WordPress Security Team's official documentation.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Stackable – Page Builder Gutenberg Blocks plugin for WordPress is vulnerable to Stored Cross-Site Scripting via block attributes in versions up to 3.19.5. This allows authenticated attackers with Author-level permissions or higher to inject malicious scripts that execute in the context of any user viewing the compromised page.

Exploit Outline

1. Authenticate as a user with at least Author-level permissions (capable of creating or editing posts). 2. Create a new post or edit an existing one using the Gutenberg editor. 3. Insert a Stackable block (such as a Heading, Button, or Container) that accepts user-defined attributes. 4. Craft a payload containing a malicious script (e.g., <script>alert(document.cookie)</script> or an HTML attribute with an event handler like 'onerror') and insert it into a vulnerable block attribute. 5. Save or publish the post. The payload is stored in the wp_posts table. 6. The script will execute in the browser of any user, including administrators, who visits the frontend page or views the block in the editor.

Check if your site is affected.

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