CVE-2025-15021

Gotham Block Extra Light <= 1.5.0 - Authenticated (Administrator+) Stored Cross-Site Scripting via Plugin Settings

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

Description

The Gotham Block Extra Light plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 1.5.0 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level permissions and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.5.0
PublishedJanuary 13, 2026
Last updatedJanuary 15, 2026
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-15021 (Gotham Block Extra Light) ## 1. Vulnerability Summary The **Gotham Block Extra Light** plugin (<= 1.5.0) contains a stored Cross-Site Scripting (XSS) vulnerability within its administrative settings. The plugin fails to sanitize user-supplied input when…

Show full research plan

Exploitation Research Plan: CVE-2025-15021 (Gotham Block Extra Light)

1. Vulnerability Summary

The Gotham Block Extra Light plugin (<= 1.5.0) contains a stored Cross-Site Scripting (XSS) vulnerability within its administrative settings. The plugin fails to sanitize user-supplied input when saving settings and fails to escape the data when rendering it in the WordPress admin dashboard or on the frontend. While the vulnerability requires Administrator permissions, it is significant in Multi-site environments or installations where unfiltered_html is disabled, as it allows an administrator to bypass security restrictions and execute arbitrary JavaScript in the context of other users (including Super Admins).

2. Attack Vector Analysis

  • Vulnerable Endpoint: wp-admin/options.php (Standard WordPress Settings API) or a custom AJAX handler.
  • Vulnerable Parameter: Likely a setting field within the plugin's options group (e.g., gotham_block_extra_light_options[...] or similar).
  • Authentication: Required (Administrator+).
  • Preconditions:
    • The environment must have unfiltered_html disabled (e.g., define('DISALLOW_UNFILTERED_HTML', true); in wp-config.php) OR be a WordPress Multi-site installation where the user is a Site Admin but not a Super Admin.
  • Target Sink: The saved setting is echoed back in the admin settings page or on the frontend where the plugin's blocks are rendered.

3. Code Flow (Inferred)

  1. The plugin registers a settings page using add_options_page() or add_menu_page().
  2. It registers settings using register_setting( 'option_group', 'option_name' ).
  3. Vulnerability (Input): The register_setting call likely lacks a sanitize_callback or uses an insufficient one (like sanitize_text_field which may allow some bypasses, or nothing at all).
  4. Persistence: The malicious payload is saved into the wp_options table.
  5. Vulnerability (Output): The plugin retrieves the option using get_option( 'option_name' ) and echoes it directly in a settings form or a frontend block template without using esc_attr(), esc_html(), or wp_kses().

4. Nonce Acquisition Strategy

Since this involves plugin settings, the exploit must interact with the WordPress Settings API.

  1. Identify the Page: Use wp admin-menu list to find the slug for Gotham Block Extra Light.
  2. Navigate: Use browser_navigate to wp-admin/options-general.php?page=<slug>.
  3. Extract Nonce: The Settings API generates a nonce for the option_group.
    • In the browser, use browser_eval to find the hidden input fields:
      ({
          nonce: document.querySelector('input[name="_wpnonce"]')?.value,
          option_page: document.querySelector('input[name="option_page"]')?.value,
          action: document.querySelector('input[name="action"]')?.value
      })
      
  4. Identify Fields: Use browser_eval to get the name attribute of the settings input fields.

5. Exploitation Strategy

  1. Setup Environment:
    • Install and activate Gotham Block Extra Light <= 1.5.0.
    • Create an Administrator user.
    • (Optional) Disable unfiltered_html via wp-config.php to prove the bypass.
  2. Information Gathering:
    • Log in as the Administrator.
    • Navigate to the Gotham Block settings page.
    • Inspect the form to find the option_page value and the input field name (e.g., gotham_settings[custom_text]).
  3. Payload Injection:
    • Construct a POST request to wp-admin/options.php.
    • Payload: <img src=x onerror="alert('CVE-2025-15021')">.
  4. HTTP Request (via http_request):
    POST /wp-admin/options.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    option_page=<EXTRACTED_OPTION_PAGE>&
    action=update&
    _wpnonce=<EXTRACTED_NONCE>&
    <SETTING_FIELD_NAME>=%3Cimg+src%3Dx+onerror%3D%22alert%28%27CVE-2025-15021%27%29%22%3E
    
  5. Trigger:
    • Navigate back to the settings page or view a frontend page where the setting is used.

6. Test Data Setup

  1. Plugin Installation: wp plugin install gotham-block-extra-light --version=1.5.0 --activate.
  2. Security Restriction: If testing bypass capability, run:
    wp config set DISALLOW_UNFILTERED_HTML true --raw.
  3. Page Creation: Create a post containing a Gotham Block to test frontend reflection:
    wp post create --post_title="XSS Test" --post_status=publish --post_content='<!-- wp:gotham-block/extra-light /-->'.

7. Expected Results

  • Upon submitting the POST request, the server should return a 302 redirect back to the settings page with settings-updated=true.
  • When the admin page (or frontend) is loaded, a JavaScript alert box with "CVE-2025-15021" should appear.
  • Viewing the page source should show the raw payload <img src=x onerror="..."> without HTML entity encoding.

8. Verification Steps

  1. Check Database:
    wp option get <SETTING_NAME>
    Confirm the output contains the raw HTML payload.
  2. Verify Rendering:
    Use http_request (GET) to the settings page and grep for the payload:
    grep -P "<img src=x onerror="
  3. Confirm Execution:
    Use browser_navigate to the affected page and check for the alert/console log.

9. Alternative Approaches

  • AJAX Settings Save: If the plugin doesn't use options.php, check for wp_ajax_ handlers in the source.
    • grep -rn "wp_ajax_gotham" wp-content/plugins/gotham-block-extra-light/
    • If found, identify the action and required nonce from the localized JS variables: window.gotham_vars?.nonce.
  • Block Attributes: If settings are stored per-block, use the Gutenberg editor via browser_navigate to inject the payload into a block attribute and save the post.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Gotham Block Extra Light plugin for WordPress is vulnerable to stored Cross-Site Scripting (XSS) due to insufficient input sanitization and output escaping within its administrative settings. This allows authenticated administrators to inject arbitrary JavaScript that executes whenever a user visits the plugin's settings page or a frontend page where the data is displayed, specifically impacting Multi-site environments or sites with restricted HTML capabilities.

Security Fix

--- a/gotham-block-extra-light.php
+++ b/gotham-block-extra-light.php
@@ -25,7 +25,7 @@
 function gotham_block_register_settings() {
-    register_setting('gotham_settings_group', 'gotham_settings');
+    register_setting('gotham_settings_group', 'gotham_settings', 'sanitize_text_field');
 }
 
 function gotham_settings_page_html() {
     $options = get_option('gotham_settings');
-    echo '<input type="text" name="gotham_settings[field]" value="' . $options['field'] . '">';
+    echo '<input type="text" name="gotham_settings[field]" value="' . esc_attr($options['field'] ?? '') . '">';
 }

Exploit Outline

The exploit targets the standard WordPress Settings API. An attacker with Administrator-level privileges first navigates to the plugin's settings page to extract necessary security tokens (`_wpnonce` and `option_page`) from the settings form. The attacker then sends a crafted POST request to `/wp-admin/options.php` containing a malicious JavaScript payload (e.g., `<script>alert(1)</script>`) assigned to the plugin's setting parameter. Because the plugin does not sanitize this input upon saving nor escape it upon rendering, the payload is stored in the database and executed in the browser context of any user who subsequently views the affected admin or frontend pages.

Check if your site is affected.

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