CVE-2026-10586

Gutenberg Essential Blocks – Page Builder for Gutenberg Blocks & Patterns <= 6.1.3 - Authenticated (Author+) Server-Side Request Forgery

highServer-Side Request Forgery (SSRF)
7.2
CVSS Score
7.2
CVSS Score
high
Severity
6.1.4
Patched in
1d
Time to patch

Description

The Gutenberg Essential Blocks – Page Builder for Gutenberg Blocks & Patterns plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 6.1.3 via the `save_ai_generated_image()` function. This makes it possible for authenticated attackers, with Author-level access and above, to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=6.1.3
PublishedJune 4, 2026
Last updatedJune 4, 2026
Affected pluginessential-blocks

What Changed in the Fix

Changes introduced in v6.1.4

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to verify and exploit **CVE-2026-10586**, an SSRF vulnerability in the **Essential Blocks** plugin. ### 1. Vulnerability Summary The vulnerability exists in the `save_ai_generated_image()` function of the Gutenberg Essential Blocks plugin (versions <= 6.1.3). T…

Show full research plan

This research plan outlines the steps to verify and exploit CVE-2026-10586, an SSRF vulnerability in the Essential Blocks plugin.

1. Vulnerability Summary

The vulnerability exists in the save_ai_generated_image() function of the Gutenberg Essential Blocks plugin (versions <= 6.1.3). This function is designed to take a URL of an AI-generated image (likely from an external service like OpenAI), fetch it, and save it to the WordPress Media Library. However, the function fails to validate the source URL, allowing an authenticated user with Author-level permissions to provide internal or arbitrary URLs, leading to Server-Side Request Forgery (SSRF).

2. Attack Vector Analysis

  • Endpoint: WordPress AJAX (/wp-admin/admin-ajax.php) or REST API. Given the plugin's architecture, this is likely a registered AJAX action.
  • Action Name: eb_save_ai_generated_image or essential_blocks_save_ai_generated_image (inferred from plugin naming conventions).
  • Vulnerable Parameter: url or image_url.
  • Required Authentication: Author level or higher (Users who can access the Gutenberg editor and use AI block features).
  • Capability: edit_posts.

3. Code Flow (Inferred)

  1. Entry Point: The user triggers an AI image generation or "Save to Library" action in the block editor.
  2. AJAX/REST Call: The frontend JS (likely in assets/admin/editor/editor.js) sends a request to the server with a URL parameter.
  3. Function Call: save_ai_generated_image( $request ) is invoked.
  4. SSRF Sink: The function calls download_url( $url ) or wp_remote_get( $url ) without restricting the URL to allowed domains (like openai.com or dalle.com).
  5. Processing: The server fetches the content from the provided URL. If it's an internal service (e.g., http://localhost:6379), the server attempts to communicate with it.

4. Nonce Acquisition Strategy

The Essential Blocks plugin localizes configuration data for the Gutenberg editor. We need to extract the nonce required for the AI-related actions.

  1. Identify Shortcode: The Essential Blocks plugin doesn't necessarily need a shortcode for editor-side vulnerabilities, but we need to be in the post editor context.
  2. Setup: Create an Author user and a new post.
  3. Navigation: Log in and navigate to the editor for that post: /wp-admin/post-new.php.
  4. Extraction:
    • The plugin likely uses EssentialBlocksLocalize or a similar object.
    • Check for nonces in the global scope:
      // Potential keys to check in browser_eval
      window.EssentialBlocksLocalize?.nonce
      window.EssentialBlocksConfig?.nonce
      window.eb_admin_data?.nonce
      
    • If the nonce is specific to the AI extension, look for:
      window.EssentialBlocksLocalize?.ai_nonce
      

5. Exploitation Strategy

Step 1: Target Identification

Search the plugin directory to find the exact AJAX action and parameter name.

grep -rn "save_ai_generated_image" .
grep -rn "wp_ajax_.*save_ai" .

Step 2: Test Internal Request (SSRF)

Once the action and nonce are found, attempt to hit an internal service. We will use a unique port to observe response differences.

HTTP Request (Example):

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=eb_save_ai_generated_image&url=http://127.0.0.1:80&_wpnonce=[NONCE]
    

Step 3: Blind Verification (Time-based or Out-of-band)

If the response does not return the content of the URL, use a collaborator URL (e.g., from interactsh or a similar tool) to confirm the request is leaving the server.

action=eb_save_ai_generated_image&url=http://[your-collaborator-id].oast.fun&_wpnonce=[NONCE]

6. Test Data Setup

  1. User Creation:
    wp user create attacker attacker@example.com --role=author --user_pass=password123
    
  2. Post Creation:
    wp post create --post_type=post --post_title="SSRF Test" --post_status=publish --post_author=$(wp user get attacker --field=ID)
    
  3. Plugin Configuration: Ensure "Essential Blocks" is active. AI features might require a (fake) API key to be set in the plugin settings to enable the UI elements, though the backend function might be callable regardless.

7. Expected Results

  • Successful Exploitation: The server returns a success message or an error indicating it tried to parse the response from the provided internal URL (e.g., "Invalid image type" if hitting a non-image internal service).
  • OOB Confirmation: A hit is recorded on the listener/collaborator URL.
  • Internal Discovery: Different response times or error messages when targeting open vs. closed internal ports (e.g., localhost:80 vs localhost:12345).

8. Verification Steps

  1. Check the WordPress Media Library to see if any "image" was attempted to be created:
    wp media list
    
  2. Verify if the plugin logged any errors in wp-content/debug.log related to the failed image download from the internal URL.

9. Alternative Approaches

  • REST API: Check if the function is exposed via a REST route: register_rest_route( 'essential-blocks/v1', '/save-ai-image' ). If so, use the X-WP-Nonce header with the REST nonce.
  • Post Meta: In some cases, the URL might be saved to post meta first and then processed. Attempt to update a post with an Essential Block and include the url in the block attributes.
  • Gopher/Dict protocols: If the underlying fetcher is curl, attempt to use gopher:// or dict:// for more advanced internal service exploitation.

Check if your site is affected.

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