[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$feWl3u019Q2t4SLBQU5ekgcman3oWePM982x5BpG-_rY":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-3367","lockme-oauth2-calendars-integration-authenticated-administrator-stored-cross-site-scripting-via-app-id-setting","Lockme OAuth2 calendars integration \u003C= 2.11.0 - Authenticated (Administrator+) Stored Cross-Site Scripting via 'App ID' Setting","The Lockme OAuth2 calendars integration plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'App ID' setting in all versions up to, and including, 2.11.0. This is due to insufficient input sanitization and output escaping. The register_setting() call on line 197 lacks a sanitize callback, allowing unsanitized data to be stored via update_option(). When the settings page is rendered, the stored value is echoed directly into an HTML input's value attribute without esc_attr() on line 212. This makes it possible for authenticated attackers, with administrator-level access and above, to inject arbitrary web scripts in the settings page that will execute whenever a user accesses the plugin settings page. Multiple fields are affected: App ID (client_id), App Secret (client_secret), Bookings ID prefix (id_prefix), and API domain (api_domain). This vulnerability is particularly impactful in WordPress multisite installations where administrators of individual sites should not be able to execute JavaScript affecting other users.","lockme-calendars-integration",null,"\u003C=2.11.0","2.11.1","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-07-10 14:05:13","2026-07-11 02:31:17",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F800b1a44-4173-4b8e-bc69-9a64218e64d6?source=api-prod",1,[22,23,24,25,26,27,28,29],"build\u002Fcomposer.lock","build\u002Fsrc\u002FPlugin.php","build\u002Fvendor\u002Fcomposer\u002Finstalled.json","build\u002Fvendor\u002Fcomposer\u002Finstalled.php","composer.lock","lockme-calendars-integration.php","readme.txt","src\u002FPlugin.php","researched",false,3,"I cannot fulfill your request to create an exploitation plan or provide actionable payloads for this vulnerability. My safety guidelines prohibit me from generating materials that facilitate the exploitation of software or provide actionable instructions for compromising specific targets.\n\nI can, however, explain the security mechanics involved in the WordPress Settings API and how to implement them securely to prevent Stored Cross-Site Scripting (XSS).\n\n### Understanding the Vulnerability: Stored XSS in Settings\n\nThe vulnerability described (CVE-2026-3367) is a classic example of a \"Source-to-Sink\" flaw where user-controlled input reaches an output function without intervening security controls.\n\n1.  **The Source:** The WordPress Settings API allows administrators to submit data via forms, which is then processed by `options.php`.\n2.  **The Storage:** If the `register_setting()` call does not include a `sanitize_callback`, WordPress stores the raw input in the `wp_options` table.\n3.  **The Sink:** When the plugin's admin page renders, it retrieves this raw data using `get_option()` and echoes it directly into the HTML (e.g., inside an `input` tag's `value` attribute).\n\n### Defensive Security Implementation\n\nTo prevent such vulnerabilities, WordPress developers must implement security at both the entry and exit points of the data.\n\n#### 1. Input Sanitization (Entry)\nWhen registering settings, a `sanitize_callback` should be used to strip or encode dangerous characters before they reach the database. This ensures \"Data Integrity.\"\n\n```php\n\u002F\u002F Correct implementation\nregister_setting('plugin-settings-group', 'plugin_settings', [\n    'sanitize_callback' => function($input) {\n        $sanitized = [];\n        if (isset($input['app_id'])) {\n            \u002F\u002F sanitize_text_field removes tags and line breaks\n            $sanitized['app_id'] = sanitize_text_field($input['app_id']);\n        }\n        if (isset($input['api_domain'])) {\n            \u002F\u002F esc_url_raw is appropriate for database storage of URLs\n            $sanitized['api_domain'] = esc_url_raw($input['api_domain']);\n        }\n        return $sanitized;\n    }\n]);\n```\n\n#### 2. Output Escaping (Exit)\nFollowing the \"Escape on Output\" principle, data should be treated as untrusted even if it was previously sanitized. The choice of escaping function depends on the HTML context:\n\n*   **Attribute Context:** When outputting data inside an HTML attribute (like `value`, `title`, or `class`), use `esc_attr()`. This prevents an attacker from breaking out of the attribute using quotes (e.g., `\">\u003Cscript>alert(1)\u003C\u002Fscript>`).\n*   **HTML Body Context:** When outputting data between tags, use `esc_html()`.\n*   **URL Context:** When outputting data in `href` or `src`, use `esc_url()`.\n\n```php\n\u002F\u002F Secure rendering of a settings field\n$options = get_option('plugin_settings');\n$app_id = $options['app_id'] ?? '';\n?>\n\u003Cinput type=\"text\" name=\"plugin_settings[app_id]\" value=\"\u003C?php echo esc_attr($app_id); ?>\" \u002F>\n\u003C?php\n```\n\n#### 3. CSRF Protection\nWordPress provides built-in protection against Cross-Site Request Forgery (CSRF) in the settings API. Using `settings_fields($option_group)` in the admin form automatically generates the necessary hidden nonce fields that WordPress verifies upon submission to `options.php`.\n\nFor further research on securing WordPress plugins, I recommend consulting the [WordPress Plugin Handbook: Security Section](https:\u002F\u002Fdeveloper.wordpress.org\u002Fplugins\u002Fsecurity\u002F) and the [OWASP XSS Prevention Cheat Sheet](https:\u002F\u002Fcheatsheetseries.owasp.org\u002Fcheatsheets\u002FCross_Site_Scripting_Prevention_Cheat_Sheet.html).","The Lockme OAuth2 calendars integration plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) in versions up to 2.11.0. This occurs because the plugin fails to sanitize user-provided settings like 'App ID' and 'App Secret' during registration and subsequently echoes these values on the administration page without proper attribute escaping.","\u002F\u002F src\u002FPlugin.php line 197\nregister_setting('lockme-admin', 'lockme_settings');\n\n---\n\n\u002F\u002F src\u002FPlugin.php line 212 (Inferred representative field rendering logic)\n\u003Cinput type=\"text\" name=\"lockme_settings[client_id]\" value=\"\u003C?php echo $this->options['client_id']; ?>\" \u002F>","--- a\u002Fsrc\u002FPlugin.php\n+++ b\u002Fsrc\u002FPlugin.php\n@@ -194,7 +194,14 @@\n \n     public function admin_register_settings(): void\n     {\n-        register_setting('lockme-admin', 'lockme_settings');\n+        register_setting('lockme-admin', 'lockme_settings', ['sanitize_callback' => function($settings) {\n+            $settings['client_id'] = sanitize_text_field($settings['client_id'] ?? '');\n+            $settings['client_secret'] = sanitize_text_field($settings['client_secret'] ?? '');\n+            $settings['id_prefix'] = sanitize_text_field($settings['id_prefix'] ?? '');\n+            $settings['api_domain'] = esc_url_raw($settings['api_domain'] ?? '');\n+            return $settings;\n+        }]);\n         add_settings_section('lockme_settings_section', 'API Settings', null, 'lockme_integration');\n \n+        \u002F\u002F When rendering fields in the settings page:\n+        \u002F\u002F echo '\u003Cinput type=\"text\" name=\"lockme_settings[client_id]\" value=\"' . esc_attr($this->options['client_id']) . '\" \u002F>';","An authenticated attacker with administrator privileges can navigate to the plugin's settings page and input a malicious payload (e.g., \">\u003Cscript>alert(1)\u003C\u002Fscript>) into the 'App ID' or 'App Secret' fields. Because the plugin lacks a sanitize_callback in the register_setting() call, the payload is saved as-is in the database. When the page is reloaded or visited by any user, the raw value is echoed into the HTML input's value attribute without escaping, allowing the script to execute in the user's browser.","gemini-3-flash-preview","2026-07-15 09:43:07","2026-07-15 09:44:13",{"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.11.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flockme-calendars-integration\u002Ftags\u002F2.11.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flockme-calendars-integration.2.11.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flockme-calendars-integration\u002Ftags\u002F2.11.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flockme-calendars-integration.2.11.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flockme-calendars-integration\u002Ftags"]