[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fneEClT7lRmlj6KMqOYNWWGwOp8uS2GeYEZKX0q11K1E":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-4146","loco-translate-reflected-cross-site-scripting-via-updatehref-parameter","Loco Translate \u003C= 2.8.2 - Reflected Cross-Site Scripting via 'update_href' Parameter","The Loco Translate plugin for WordPress is vulnerable to Reflected Cross-Site Scripting via the ‘update_href’ parameter in all versions up to, and including, 2.8.2 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick a user into performing an action such as clicking on a link.","loco-translate",null,"\u003C=2.8.2","2.8.3","medium",6.1,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:R\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-03-30 15:35:09","2026-03-31 04:25:34",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Ffaa6c744-7586-47ee-b2ce-af972ee8b4f7?source=api-prod",1,[22,23,24,25,26,27,28,29],"languages\u002Floco-translate.pot","lib\u002Fdata\u002Flocales.php","loco.php","pub\u002Fjs\u002Fmin\u002Fadmin.js","readme.txt","src\u002Fadmin\u002Fconfig\u002FVersionController.php","src\u002Fajax\u002FFsReferenceController.php","src\u002Ffs\u002FLocations.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-4146 (Loco Translate Reflected XSS)\n\n## 1. Vulnerability Summary\nThe **Loco Translate** plugin (versions \u003C= 2.8.2) is vulnerable to **Reflected Cross-Site Scripting (XSS)** via the `update_href` parameter. The vulnerability exists in the plugin's administration settings, specifically within the version\u002Fupgrade interface. The plugin fails to sanitize or escape the `update_href` URL parameter before rendering it into an `href` attribute of an anchor tag in the administrative dashboard.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `wp-admin\u002Fadmin.php`\n- **Query Parameters:** \n    - `page=loco-config`: The main configuration page for Loco Translate.\n    - `tab=version`: The specific tab handled by `Loco_admin_config_VersionController`.\n    - `update_href`: The payload carrier.\n- **Authentication:** Required (Administrator). However, the attack is classified as **Unauthenticated** (CVSS `PR:N`) because an attacker can craft a malicious link and trick a logged-in administrator into clicking it.\n- **Vulnerable Sink:** An `\u003Ca>` tag in `tpl\u002Fadmin\u002Fconfig\u002Fversion.php` that echoes the `update_href` variable without using `esc_url()`.\n\n## 3. Code Flow\n1. **Entry Point:** A user (administrator) navigates to `wp-admin\u002Fadmin.php?page=loco-config&tab=version&update_href=javascript:alert(document.domain)`.\n2. **Controller Dispatch:** The WordPress admin menu system dispatches the request to Loco Translate's internal router. The `tab=version` parameter identifies `Loco_admin_config_VersionController` as the active controller.\n3. **Variable Population:** The `Loco_mvc_Controller` (base class) or the `VersionController` itself populates its internal data view array from the request. In `src\u002Fadmin\u002Fconfig\u002FVersionController.php`, the `render()` method is called.\n4. **Conditional Logic:** \n   - At line 32, the code checks for plugin updates via `get_site_transient('update_plugins')`.\n   - If an update is available, `setLocoUpdate()` (line 70) is called, which calls `$this->set('update_href', ...)` to define the variable internally.\n   - **The Flaw:** If no update is found, `setLocoUpdate()` is not called. However, if the `update_href` parameter is provided in the URL, the underlying MVC framework or the template `tpl\u002Fadmin\u002Fconfig\u002Fversion.php` still perceives the variable as being set (inherited from the `$_GET` request) and renders the update UI.\n5. **Sink:** The template `tpl\u002Fadmin\u002Fconfig\u002Fversion.php` (referenced at line 62) outputs the value of `update_href` inside an `href` attribute. Since it is not wrapped in `esc_url()`, the `javascript:` protocol is allowed to execute.\n\n## 4. Nonce Acquisition Strategy\nThis is a **Reflected XSS** via a `GET` request to an administrative page. \n- Viewing the `loco-config` page does not typically require a functional nonce for the initial page load (WordPress relies on standard `manage_options` capability checks for menu pages).\n- The attack itself is the URL. Once the administrator clicks the crafted link, the XSS executes in their context.\n- **No nonce is required** to trigger the reflection on the page.\n\n## 5. Exploitation Strategy\n### Step-by-Step Plan:\n1. **Target Identification:** Verify the plugin is installed and version is \u003C= 2.8.2.\n2. **Payload Crafting:** Create a URL that points to the Loco Translate Version tab with a `javascript:` payload.\n   - Payload: `javascript:alert(document.domain)`\n   - Full URL: `\u002Fwp-admin\u002Fadmin.php?page=loco-config&tab=version&update_href=javascript:alert(document.domain)`\n3. **Execution:**\n   - Use `browser_navigate` to visit the crafted URL as an Administrator.\n   - The page will render. Even if no update is actually available for Loco Translate, the template logic likely checks `if ($update_href)` and renders the update link because the parameter is present in the URL.\n4. **Trigger:**\n   - Locate the link in the DOM. Based on the `.pot` file, it will be near the text \"A newer version of Loco Translate is available for download\".\n   - Use `browser_click` or `browser_eval` to click the link.\n5. **Verification:** Detect the alert box to confirm XSS.\n\n## 6. Test Data Setup\n1. **User:** Create an administrator user (e.g., `admin`\u002F`password`).\n2. **Plugin:** Install and activate **Loco Translate 2.8.2**.\n3. **Environment:** No specific translations or bundles are needed for this specific XSS, as it resides in the configuration\u002Fversion view.\n\n## 7. Expected Results\n- When the Administrator navigates to the malicious URL, a link (or button) intended for \"Update\" or \"Download\" will appear on the page.\n- The HTML source for this link will look like: `\u003Ca href=\"javascript:alert(document.domain)\" ...>...\u003C\u002Fa>`.\n- Clicking the link will trigger a JavaScript alert displaying the site's domain.\n\n## 8. Verification Steps\n1. **Manual Inspection:**\n   - Use `http_request` to fetch the page: `GET \u002Fwp-admin\u002Fadmin.php?page=loco-config&tab=version&update_href=javascript:alert(1)`\n   - Search the response body for the string `href=\"javascript:alert(1)\"`.\n2. **Automated Trigger:**\n   - Use `browser_navigate` to the URL.\n   - Execute `browser_eval(\"document.querySelector('a[href^=\\\"javascript:\\\"]').click()\")`.\n   - Check for the presence of an browser alert.\n\n## 9. Alternative Approaches\nIf the `update_href` is reflected but hidden (e.g., if the \"Update\" notice requires specific conditions to show), try the following:\n1. **Bypass Display Logic:** Check if `wpupdate_href` (referenced as a commented-out candidate in `VersionController.php`) is also vulnerable.\n2. **Attribute Breakout:** If the value is reflected in a context where `javascript:` is blocked but quotes are not escaped, use an attribute breakout:\n   - `update_href=x\" onmouseover=\"alert(1)\"`\n3. **Transient Mocking:** If the link *only* appears when an update is truly available, use `wp_cli` to temporarily set a fake update transient:\n   ```bash\n   wp eval 'set_site_transient(\"update_plugins\", (object)[\"response\" => [\"loco-translate\u002Floco.php\" => (object)[\"new_version\" => \"9.9.9\"]]]);'\n   ```\n   This will force `VersionController::render` to call `setLocoUpdate()`, potentially exposing the sink more reliably.","The Loco Translate plugin for WordPress is vulnerable to Reflected Cross-Site Scripting via the 'update_href' parameter in the administrative settings. This occurs because the plugin's MVC framework allows uninitialized template variables to be populated from request parameters, which are then rendered into an anchor tag's href attribute without sanitization.","\u002F\u002F src\u002Fadmin\u002Fconfig\u002FVersionController.php:25\npublic function render(){\n    \n    $title = __('Plugin settings','loco-translate');\n    $breadcrumb = new Loco_admin_Navigation;\n    $breadcrumb->add( $title );\n    \n    \u002F\u002F current plugin version\n    $version = loco_plugin_version();\n    if( $updates = get_site_transient('update_plugins') ){\n        $key = loco_plugin_self();\n        if( isset($updates->response[$key]) ){\n            $latest = $updates->response[$key]->new_version;\n            \u002F\u002F if current version is lower than latest, prompt update\n            if( version_compare($version,$latest,'\u003C') ){\n                $this->setLocoUpdate($latest);\n            }\n        }\n    }\n    \u002F\u002F ... (truncated)\n\n--- \n\n\u002F\u002F src\u002Fadmin\u002Fconfig\u002FVersionController.php:69\nprivate function setLocoUpdate( $version ){\n    $action = 'upgrade-plugin_'.loco_plugin_self();\n    $link = admin_url( 'update.php?action=upgrade-plugin&plugin='.rawurlencode(loco_plugin_self()) );\n    $this->set('update', $version );\n    $this->set('update_href', wp_nonce_url( $link, $action ) );\n}","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Floco-translate\u002F2.8.2\u002Fsrc\u002Fadmin\u002Fconfig\u002FVersionController.php\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Floco-translate\u002F2.8.3\u002Fsrc\u002Fadmin\u002Fconfig\u002FVersionController.php\n@@ -22,6 +22,7 @@\n         $title = __('Plugin settings','loco-translate');\n         $breadcrumb = new Loco_admin_Navigation;\n         $breadcrumb->add( $title );\n+        $this->setLocoUpdate('0');\n         \n         \u002F\u002F current plugin version\n         $version = loco_plugin_version();\n@@ -70,5 +71,11 @@\n     private function setLocoUpdate( $version ){\n         $action = 'upgrade-plugin_'.loco_plugin_self();\n         $link = admin_url( 'update.php?action=upgrade-plugin&plugin='.rawurlencode(loco_plugin_self()) );\n-        $this->set('update', $version );\n-        $this->set('update_href', wp_nonce_url( $link, $action ) );\n+        if ( '0' === $version ) {\n+            $this->set('update', '' );\n+            $this->set('update_href', '' );\n+        }\n+        else {\n+            $this->set('update', $version );\n+            $this->set('update_href', wp_nonce_url( $link, $action ) );\n+        }\n     }","To exploit this vulnerability, an attacker crafts a URL targeting the Loco Translate version settings page: `\u002Fwp-admin\u002Fadmin.php?page=loco-config&tab=version`. The attacker appends a malicious `update_href` parameter containing a `javascript:` payload (e.g., `update_href=javascript:alert(document.domain)`). Because the plugin's MVC pattern defaults to pulling view variables from the global request if they are not explicitly set by the controller, and the 'Version' tab only sets `update_href` when a plugin update is available, the malicious parameter is reflected into the 'Update' link's href attribute. The attacker then tricks a logged-in administrator into visiting the URL and clicking the resulting link to execute the script.","gemini-3-flash-preview","2026-04-17 22:14:37","2026-04-17 22:15:17",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","2.8.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Floco-translate\u002Ftags\u002F2.8.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Floco-translate.2.8.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Floco-translate\u002Ftags\u002F2.8.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Floco-translate.2.8.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Floco-translate\u002Ftags"]