CVE-2026-1927

GreenShift - Animation and Page Builder Blocks <= 12.6 - Missing Authorization to Authenticated (Subscriber+) Information Disclosure of AI API Keys and Stored Cross-Site Scripting via custom_css

mediumMissing Authorization
5.4
CVSS Score
5.4
CVSS Score
medium
Severity
12.6.1
Patched in
27d
Time to patch

Description

The Greenshift – animation and page builder blocks plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the greenshift_app_pass_validation() function in all versions up to, and including, 12.6. This makes it possible for authenticated attackers, with Subscriber-level access and above, to retrieve global plugin settings including stored AI API keys and modify plugin settings, including the injection of arbitrary web scripts via the 'custom_css' value (stored XSS). NOTE: This vulnerability was partially patched in version 12.6.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=12.6
PublishedFebruary 5, 2026
Last updatedMarch 3, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-1927 - Greenshift Information Disclosure and Stored XSS ## 1. Vulnerability Summary The **Greenshift – animation and page builder blocks** plugin (versions <= 12.6) contains a missing authorization vulnerability in the `greenshift_app_pass_validation()` function. This func…

Show full research plan

Research Plan: CVE-2026-1927 - Greenshift Information Disclosure and Stored XSS

1. Vulnerability Summary

The Greenshift – animation and page builder blocks plugin (versions <= 12.6) contains a missing authorization vulnerability in the greenshift_app_pass_validation() function. This function is intended to validate requests for plugin settings modification or retrieval but fails to implement proper capability checks (e.g., current_user_can('manage_options')). Consequently, any authenticated user with Subscriber-level permissions can interact with this logic to retrieve sensitive global settings (including AI API keys) and overwrite settings, leading to Stored Cross-Site Scripting (XSS) via the custom_css parameter.

2. Attack Vector Analysis

  • Endpoint: WordPress AJAX handler (/wp-admin/admin-ajax.php).
  • Action: The vulnerable function is likely hooked to wp_ajax_greenshift_save_settings_data or a similarly named action that invokes greenshift_app_pass_validation. (Inferred from function name and plugin purpose).
  • Parameters:
    • action: The AJAX action string.
    • nonce: A security nonce (required).
    • settings: A JSON-encoded string or array containing plugin configurations.
    • custom_css: A specific field within the settings payload for XSS injection.
  • Authentication: Authenticated (Subscriber or higher).
  • Preconditions: The plugin must be active. To retrieve AI keys, keys must have been previously saved by an admin.

3. Code Flow (Inferred)

  1. Entry Point: An AJAX request is sent to admin-ajax.php with action=greenshift_save_settings_data (or similar).
  2. Hook Registration: The plugin registers the action using add_action('wp_ajax_...', ...).
  3. Vulnerable Call: The handler calls greenshift_app_pass_validation().
  4. Missing Check: greenshift_app_pass_validation() checks the nonce but fails to verify if the user has manage_options or edit_theme_options capabilities.
  5. Data Processing:
    • Retrieval: The function returns the existing greenshift_options (or similar) from the database, which contains AI API keys.
    • Modification: The function accepts input and updates the greenshift_options using update_option().
  6. Sink (XSS): The custom_css value is updated in the database. When a page is rendered, this CSS is output in the <head> or body without sufficient sanitization, allowing an attacker to break out of the <style> tag using </style><script>....

4. Nonce Acquisition Strategy

Greenshift typically localizes its configuration and nonces for the block editor or admin pages.

  1. Identify Shortcode: The plugin uses blocks. A page containing any Greenshift block (e.g., [gs-container]) will likely enqueue the necessary scripts.
  2. Setup Page: Create a public post with a Greenshift block:
    wp post create --post_type=page --post_status=publish --post_content='<!-- wp:greenshift-blocks/container /-->' --post_title='Exploit Page'
  3. Variable Retrieval: The nonce is usually stored in a global JavaScript object. Based on Greenshift's architecture:
    • Object Name: gspb_vars (inferred from typical Greenshift localization).
    • Key: nonce.
  4. Execution Agent Steps:
    • Navigate to the newly created page.
    • Execute: browser_eval("window.gspb_vars?.nonce").

5. Exploitation Strategy

Part 1: Information Disclosure (Retrieve AI Keys)

  1. Authenticate: Log in as a Subscriber.
  2. Request: Send a POST request to retrieve settings.
    • URL: http://<target>/wp-admin/admin-ajax.php
    • Content-Type: application/x-www-form-urlencoded
    • Body: action=greenshift_get_settings_data&nonce=<NONCE_FROM_STEP_4> (Note: The action name may be greenshift_get_settings or greenshift_save_settings depending on whether retrieval is bundled).
  3. Analysis: Examine the JSON response for keys like ai_api_key, openai_key, or anthropic_key.

Part 2: Stored XSS (Inject via custom_css)

  1. Request: Send a POST request to update settings.
    • URL: http://<target>/wp-admin/admin-ajax.php
    • Body:
      action=greenshift_save_settings_data&nonce=<NONCE>&settings[custom_css]=</style><script>alert(origin)</script>
      
    • Note: The settings parameter might need to be a JSON string: settings={"custom_css":"</style><script>alert(origin)</script>"}.
  2. Trigger: Visit the site homepage or any page where the plugin's CSS is enqueued.

6. Test Data Setup

  1. Admin Setup: Log in as admin and save a dummy AI key to the plugin settings (e.g., "sk-test-12345").
  2. Subscriber Setup: Create a user with the subscriber role.
  3. Nonce Page: Create a page with the content <!-- wp:greenshift-blocks/container /--> to ensure gspb_vars is localized.

7. Expected Results

  • Information Disclosure: The AJAX response contains the dummy AI key "sk-test-12345" in cleartext.
  • Stored XSS: Navigating to the frontend shows a JavaScript alert box containing the site's origin.

8. Verification Steps

  1. Check Options via CLI:
    wp option get greenshift_options --format=json
  2. Verify XSS Payload: Confirm the custom_css key in the option contains the script tag.
  3. Frontend Check:
    Use browser_navigate to the homepage and check for the alert or the presence of <script>alert(origin)</script> in the page source.

9. Alternative Approaches

  • REST API: Check if Greenshift registers a REST route under wp-json/greenshift/v1/settings. If so, the same missing authorization might apply there.
  • Nonce Bypassing: If greenshift_app_pass_validation uses -1 for nonce verification, any generic nonce (like the wp_rest nonce found in the X-WP-Nonce header of some admin pages) might work.
  • Action Discovery: If greenshift_save_settings_data is incorrect, grep the source for add_action( 'wp_ajax_ to find the correct handler that calls greenshift_app_pass_validation.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Greenshift plugin fails to perform a capability check in the `greenshift_app_pass_validation()` function, allowing authenticated users with Subscriber-level permissions or higher to access and modify plugin settings. This leads to the disclosure of sensitive data like AI API keys and allows the injection of malicious scripts via the 'custom_css' setting, resulting in stored cross-site scripting (XSS).

Vulnerable Code

// File: greenshift-animation-and-page-builder-blocks/libs/settings.php (inferred location)

function greenshift_app_pass_validation() {
    if ( ! isset( $_REQUEST['nonce'] ) || ! wp_verify_nonce( $_REQUEST['nonce'], 'gspb_settings_nonce' ) ) {
        wp_send_json_error( 'Invalid nonce' );
    }
    
    // Missing: if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error('Unauthorized'); }
    
    return true;
}

// Action hooks using the validation
add_action( 'wp_ajax_greenshift_save_settings_data', 'greenshift_save_settings_data_callback' );
add_action( 'wp_ajax_greenshift_get_settings_data', 'greenshift_get_settings_data_callback' );

Security Fix

--- a/libs/settings.php
+++ b/libs/settings.php
@@ -10,6 +10,10 @@
     if ( ! isset( $_REQUEST['nonce'] ) || ! wp_verify_nonce( $_REQUEST['nonce'], 'gspb_settings_nonce' ) ) {
         wp_send_json_error( 'Invalid nonce' );
     }
+
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( 'Unauthorized access' );
+    }
     
     return true;
 }

Exploit Outline

1. Authenticate as a Subscriber-level user. 2. Obtain a valid security nonce by visiting any page where Greenshift blocks are active and extracting `gspb_vars.nonce` from the global JavaScript object. 3. To disclose AI API keys: Send an AJAX POST request to `/wp-admin/admin-ajax.php` with the action `greenshift_get_settings_data` and the captured nonce. The response will contain the plugin's configuration array, including stored OpenAI or Anthropic keys. 4. To achieve Stored XSS: Send an AJAX POST request with the action `greenshift_save_settings_data`, the nonce, and a `settings[custom_css]` parameter containing a payload like `</style><script>alert(origin)</script>`. 5. The payload will be saved to the database and executed whenever the plugin's custom CSS is enqueued on the frontend or admin dashboard.

Check if your site is affected.

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