Widgets for Google Reviews <= 13.3 - Authenticated (Editor+) Stored Cross-Site Scripting via 'fomo-title' and 'fomo-text' Parameters
Description
The Widgets for Google Reviews plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 13.3 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with editor-level permissions and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=13.3What Changed in the Fix
Changes introduced in v13.3.1
Source Code
WordPress.org SVNThis research plan outlines the technical methodology for analyzing and validating CVE-2026-11591, a Stored Cross-Site Scripting (XSS) vulnerability in the **Widgets for Google Reviews** plugin. ### 1. Vulnerability Summary The vulnerability exists due to the "Widgets for Google Reviews" plugin fai…
Show full research plan
This research plan outlines the technical methodology for analyzing and validating CVE-2026-11591, a Stored Cross-Site Scripting (XSS) vulnerability in the Widgets for Google Reviews plugin.
1. Vulnerability Summary
The vulnerability exists due to the "Widgets for Google Reviews" plugin failing to sufficiently sanitize and escape the fomo-title and fomo-text parameters within its admin settings. These parameters are part of the "FOMO" (Fear Of Missing Out) notification feature, which displays small popups to users. Because these values are stored in the database and subsequently rendered into both the admin dashboard and public-facing pages without proper output escaping (e.g., via esc_html or esc_attr), an authenticated attacker with Editor-level permissions can inject arbitrary JavaScript.
2. Attack Vector Analysis
- Vulnerable Endpoint: The settings update handler, typically accessed via
wp-admin/admin-ajax.phporwp-admin/options.php. - Vulnerable Parameters:
fomo-titleandfomo-text. - Required Authentication: Editor or higher.
- Contextual Trigger: The XSS executes when an administrator visits the plugin settings page or when a visitor views a page where the Google Reviews/FOMO widget is active.
- Preconditions: In standard WordPress environments, Editors have the
unfiltered_htmlcapability. This vulnerability is specifically relevant in Multisite environments (where only Super Admins haveunfiltered_html) or hardened installations whereDISALLOW_UNFILTERED_HTMLis set totrue.
3. Code Flow (Inferred)
As the full PHP source is not provided, the following flow is inferred based on standard Trustindex plugin architecture and the provided CSS (admin-page-settings.css):
- Entry Point: An Editor submits a settings form on the Trustindex configuration page (
#trustindex-plugin-settings-page). - Processing: The plugin receives the request. A handler (likely in an admin-specific class) uses
update_option()or a similar function to save thefomo-titleandfomo-textvalues to thewp_optionstable. - Storage: The values are stored raw or with insufficient sanitization (e.g., only using
sanitize_text_fieldwhich does not strip all HTML tags relevant to attribute-based XSS). - Sink (Rendering): When the widget or settings page is loaded, the plugin retrieves these options using
get_option(). The values are then echoed directly into the HTML:- Admin Side: Within the settings preview or configuration form.
- Frontend Side: Inside the FOMO notification template rendered by the plugin's JavaScript or PHP.
4. Nonce Acquisition Strategy
To interact with the settings programmatically, a valid WordPress nonce is required to bypass CSRF protections.
- Identify Shortcode: Based on
readme.txt, the plugin uses shortcodes. A common shortcode for this plugin is[trustindex no-registration=google](inferred). - Setup: Create a page with the plugin's functionality to ensure scripts are enqueued.
wp post create --post_type=page --post_status=publish --post_content='[trustindex no-registration=google]'
- Extraction: Navigate to the page or the plugin settings menu. The plugin localizes its settings via
wp_localize_script.- Variable Name: Look for a global JS object like
trustindex_settingsorti_admin_pages(inferred). - Browser Eval:
browser_eval("window.ti_admin_pages?.nonce")orbrowser_eval("window.trustindex_settings?.ajax_nonce").
- Variable Name: Look for a global JS object like
5. Exploitation Strategy
This strategy validates the storage and execution of a benign script.
Step 1: Save Malicious Settings
Submit a POST request to the AJAX handler (typically wp-admin/admin-ajax.php).
- Tool:
http_request - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Parameters (Inferred):
action:trustindex_save_settings(inferred)nonce:[EXTRACTED_NONCE]fomo-title:"><script>alert('title_xss')</script>fomo-text:"><img src=x onerror=alert('text_xss')>
Step 2: Trigger the XSS
Navigate to the frontend page containing the widget or the plugin settings page.
- Tool:
browser_navigate - Target:
https://[TARGET_URL]/wp-admin/admin.php?page=trustindex-google-reviews(inferred)
6. Test Data Setup
- Environment: WordPress Multisite installation (to ensure
unfiltered_htmlis restricted). - Plugin: Install "Widgets for Google Reviews" version 13.3.
- User: Create a user with the 'Editor' role.
- Configuration: Enable the "FOMO" notification feature within the plugin settings.
7. Expected Results
- The POST request should return a success status (e.g.,
{"success": true}). - When navigating to the target page, the browser should trigger the
alertboxes, confirming that the<script>and<img>tags were rendered into the DOM without escaping.
8. Verification Steps
After the HTTP request, verify the database state via WP-CLI:
# Check if the payload is stored in the options table
wp option get trustindex_google_reviews_settings --format=json | grep "script"
9. Remediation (Defensive Focus)
The vulnerability can be remediated by applying the following security principles:
- Sanitization: Use
wp_kses()with a strict whitelist of allowed tags for any field intended to support limited HTML, orsanitize_text_field()for plain text fields. - Output Escaping: This is the most critical step. Every instance where these options are displayed must be wrapped in an escaping function:
- Use
esc_html()if the data is inside a standard HTML tag. - Use
esc_attr()if the data is inside an HTML attribute (e.g.,value="..."). - Example:
echo '<div class="ti-fomo-title">' . esc_html( $fomo_title ) . '</div>';
- Use
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.