[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fntwEEn2j6koxLkvjFzq5b5YOs0Uo7N9QtgoDALF_oBY":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,"source_links":41},"CVE-2026-2840","email-encoder-protect-email-addresses-and-phone-numbers-authenticated-contributor-stored-cross-site-scripting-via-eebmai","Email Encoder – Protect Email Addresses and Phone Numbers \u003C= 2.4.4 - Authenticated (Contributor+) Stored Cross-Site Scripting via eeb_mailto Shortcode","The Email Encoder – Protect Email Addresses and Phone Numbers plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'eeb_mailto' shortcode in all versions up to, and including, 2.4.4 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","email-encoder-bundle",null,"\u003C=2.4.4","2.4.5","medium",6.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-15 18:24:03","2026-04-15 18:24:05",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F9987b5b4-33d8-4446-acbe-58c6cb5604df?source=api-prod",0,[22,23,24,25,26,27,28,29],"config\u002FSettingsConfig.php","core\u002Fclass-email-encoder-bundle.php","core\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-ajax.php","core\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-helpers.php","core\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-settings.php","core\u002Fincludes\u002Ffunctions\u002Ftemplate-tags.php","core\u002Fincludes\u002Fintegrations\u002Fclasses\u002Favada_builder.php","core\u002Fincludes\u002Fintegrations\u002Fclasses\u002Fbricks_builder.php","researched",false,3,"This research plan targets a Stored Cross-Site Scripting (XSS) vulnerability in the **Email Encoder – Protect Email Addresses and Phone Numbers** plugin. The vulnerability allows a Contributor-level user to inject arbitrary JavaScript via the `[eeb_mailto]` shortcode.\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Stored Cross-Site Scripting (XSS)\n*   **Component:** `eeb_mailto` shortcode handler.\n*   **Affected Versions:** \u003C= 2.4.4\n*   **Mechanism:** The plugin fails to sanitize or escape attributes passed to the `[eeb_mailto]` shortcode, specifically the `display` attribute (and potentially `extra_attrs`). When the plugin \"encodes\" the email to protect it from bots (often using JavaScript `document.write` or similar methods), it includes the malicious payload in the output without sufficient filtering.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** WordPress Post Editor (via `wp-admin\u002Fpost-new.php` or REST API).\n*   **Action:** Creating or updating a post\u002Fpage containing the `[eeb_mailto]` shortcode.\n*   **Role Required:** Contributor or higher (any role capable of using shortcodes).\n*   **Payload Parameter:** Shortcode attributes (e.g., `display`, `extra_attrs`).\n*   **Preconditions:** The plugin must be active. The default protection method (`with_javascript`) is typically the most susceptible to XSS in this context.\n\n### 3. Code Flow\n1.  **Entry Point:** A user with Contributor permissions saves a post containing: `[eeb_mailto email=\"test@example.com\" display=\"\u003Cimg src=x onerror=alert(1)>\"]`.\n2.  **Registration:** The shortcode is registered in `Legacy\\EmailEncoderBundle\\Email_Encoder_Settings` via the `$template_tags` array (mapping `eeb_mailto` to `template_tag_eeb_mailto`).\n3.  **Execution:** When the post is rendered, WordPress calls the handler. According to `core\u002Fincludes\u002Ffunctions\u002Ftemplate-tags.php`, this calls `EEB()->functions->eeb_mailto( ...$args )`.\n4.  **Processing (Inferred):** The `Functions::eeb_mailto` method processes the attributes. If the `display` attribute is not escaped using `esc_html()` or `wp_kses()`, the raw HTML is carried into the protection logic.\n5.  **Sink:** The logic (similar to the AJAX `handle()` method in `class-email-encoder-bundle-ajax.php`) constructs an `\u003Ca>` tag:\n    `$link = '\u003Ca href=\"mailto:' . $email . '\" ...>' . $display . '\u003C\u002Fa>';`\n6.  **Protection Layer:** If the \"Protect using Javascript\" method is active, this `$link` string is passed to an encoder. Many encoders in this plugin simply obfuscate the string and use a JS-based decoder on the frontend.\n7.  **Execution:** When a victim (e.g., Admin) views the post, the JS decoder reconstructs the `$link` and inserts it into the DOM, executing the `onerror` payload.\n\n### 4. Nonce Acquisition Strategy\nThis vulnerability is triggered by **saving a post**, which uses standard WordPress core nonces for the Gutenberg editor or Classic editor.\n*   The PoC agent does not need to extract a plugin-specific nonce to exploit the shortcode.\n*   The agent should use `wp-cli` to create the post, which bypasses the need for manual nonce management in the browser.\n\n### 5. Exploitation Strategy\n1.  **Authentication:** Login as a user with the **Contributor** role.\n2.  **Payload Injection:** Create a new post containing the malicious shortcode.\n    *   **Payload 1 (Tag-based):** `[eeb_mailto email=\"attacker@example.com\" display=\"\u003Cimg src=x onerror=alert(window.origin)>\"]`\n    *   **Payload 2 (Attribute Breakout):** `[eeb_mailto email=\"attacker@example.com\" extra_attrs='onmouseover=alert(1)']`\n3.  **Trigger:** As an **Administrator**, navigate to the newly created post on the frontend.\n4.  **Observation:** Verify that the JavaScript executes in the Admin's browser context.\n\n### 6. Test Data Setup\n1.  **Target User:** Create a contributor user:\n    `wp user create attacker attacker@example.com --role=contributor --user_pass=password123`\n2.  **Malicious Post:** Use WP-CLI to create the post as the contributor:\n    ```bash\n    wp post create --post_type=post --post_status=publish --post_title=\"Contact Us\" \\\n      --post_content='Please contact us at: [eeb_mailto email=\"test@example.com\" display=\"\u003Cimg src=x onerror=alert(document.domain)>\"]' \\\n      --post_author=$(wp user get attacker --field=ID)\n    ```\n3.  **Plugin Config:** Ensure the default \"Protect emails using: automatically the best method (including javascript)\" is selected in settings (this is the default state).\n\n### 7. Expected Results\n*   The shortcode should be rendered by the plugin.\n*   The HTML source of the page will contain the encoded version of the link.\n*   Upon page load, the plugin's JavaScript will decode the payload.\n*   The browser will attempt to render the `\u003Cimg>` tag with an invalid `src`, triggering the `onerror` event and showing an alert box with the domain.\n\n### 8. Verification Steps\n1.  **Check Post Content:**\n    `wp post get \u003CPOST_ID> --field=post_content`\n2.  **Examine Frontend Output:** Use the `http_request` tool to fetch the post URL and check for the obfuscated string or the injected payload:\n    ```bash\n    # Look for the encoded snippet or evidence of the encoder JS\n    http_request http:\u002F\u002Flocalhost:8080\u002F?p=\u003CPOST_ID>\n    ```\n3.  **Verify Execution:** Use `browser_navigate` to the post URL and check for the `alert` or presence of the injected element in the DOM using `browser_eval`.\n\n### 9. Alternative Approaches\n*   **Method Obfuscation:** If the default JS method is patched, try switching the plugin settings to `char_encode` or `without_javascript` via `wp option update WP_Email_Encoder_Bundle_options ...` to see if the `display` attribute remains unescaped in other protection modes.\n*   **Shortcode Content:** Test if the shortcode supports a content block instead of an attribute: `[eeb_mailto email=\"...\"]\u003Cscript>alert(1)\u003C\u002Fscript>[\u002Feeb_mailto]`.\n*   **AJAX Endpoint:** While the description focuses on the shortcode, the AJAX handler `eeb_get_email_form_output` in `class-email-encoder-bundle-ajax.php` uses `wp_kses_post` on `eebDisplay`. If the shortcode handler *omits* this check entirely, that confirms the source of the vulnerability.","The Email Encoder plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the 'eeb_mailto' shortcode due to insufficient sanitization and output escaping of attributes like 'display' and 'extra_attrs'. This allows authenticated attackers with Contributor-level permissions or higher to inject arbitrary JavaScript that executes when a user, such as an administrator, views the affected post or page.","\u002F\u002F core\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-ajax.php:67-68\n$class     = esc_attr( $this->getSetting( 'class_name', true ) );\n$protect   = __( $this->getSetting( 'protection_text', true ), 'email-encoder-bundle' );\n$link      = '\u003Ca href=\"mailto:' . $email . '\" class=\"' . $class . '\">' . $display . '\u003C\u002Fa>';\n\n---\n\n\u002F\u002F core\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-helpers.php:177-198\npublic function sanitize_html_attributes( $extra_attrs ){\n\n\t$allowed_attrs = [ 'href', 'title', 'rel', 'class', 'id', 'style', 'target' ];\n\n\t\u002F\u002F Use a regular expression to match attributes and their values\n\tpreg_match_all('\u002F(\\w+)=(\"[^\"]*\"|\\'[^\\']*\\')\u002F', $extra_attrs, $matches, PREG_SET_ORDER);\n\n\t$sanitized_attrs = [];\n\n\tforeach ( $matches as $match ) {\n\n\t\t\u002F\u002FSkip undefined arguments\n\t\tif( ! in_array( $match[1], $allowed_attrs ) ){\n\t\t\tcontinue;\n\t\t}\n\n\t\t\u002F\u002F $match[1] is the attribute name, $match[2] is the attribute value including quotes\n\t\t$sanitized_name = sanitize_key( $match[1] ); \u002F\u002F Sanitize the attribute name\n\t\t$sanitized_value = esc_attr( trim( $match[2], '\"\\'' ) ); \u002F\u002F Remove quotes and escape the value\n\t\t$sanitized_value = str_replace( '\\\\', '', $sanitized_value ); \u002F\u002F Remove quotes and escape the value","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Femail-encoder-bundle\u002F2.4.4\u002Fconfig\u002FSettingsConfig.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Femail-encoder-bundle\u002F2.4.5\u002Fconfig\u002FSettingsConfig.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Femail-encoder-bundle\u002F2.4.4\u002Fconfig\u002FSettingsConfig.php\t2025-12-23 05:08:10.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Femail-encoder-bundle\u002F2.4.5\u002Fconfig\u002FSettingsConfig.php\t2026-03-30 04:07:02.000000000 +0000\n@@ -1,4 +1,5 @@\n \u003C?php\n+if ( ! defined( 'ABSPATH' ) ) exit;\n \n return [\n \n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Femail-encoder-bundle\u002F2.4.4\u002Fcore\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-ajax.php\t2026-02-16 05:52:16.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Femail-encoder-bundle\u002F2.4.5\u002Fcore\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-ajax.php\t2026-03-30 04:07:02.000000000 +0000\n@@ -65,7 +67,7 @@\n         $EEB       = Email_Encoder::instance();\n \n         $class     = esc_attr( $this->getSetting( 'class_name', true ) );\n-        $protect   = __( $this->getSetting( 'protection_text', true ), 'email-encoder-bundle' );\n+        $protect   = (string) $this->getSetting( 'protection_text', true );\n         $link      = '\u003Ca href=\"mailto:\" . $email . \"' class='\" . $class . \"'>\" . $display . \"\u003C\u002Fa>\";\n \n         switch ( $method ) {\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Femail-encoder-bundle\u002F2.4.4\u002Fcore\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-helpers.php\t2026-02-16 05:52:16.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Femail-encoder-bundle\u002F2.4.5\u002Fcore\u002Fincludes\u002Fclasses\u002Fclass-email-encoder-bundle-helpers.php\t2026-03-30 04:07:02.000000000 +0000\n@@ -79,7 +79,7 @@\n \t\tob_start();\n \t\t?>\n-\t\t\u003Cdiv class=\"notice \u003C?php echo $notice; ?> \u003C?php echo $isit; ?>\">\n-\t\t\t\u003Cp>\u003C?php echo $validated_content; ?>\u003C\u002Fp>\n+\t\t\u003Cdiv class=\"notice \u003C?php echo esc_attr( $notice ); ?> \u003C?php echo esc_attr( $isit ); ?>\">\n+\t\t\t\u003Cp>\u003C?php echo wp_kses_post( $validated_content ); ?>\u003C\u002Fp>\n \t\t\u003C\u002Fdiv>\n \t\t\u003C?php\n \t\t$res = ob_get_clean();\n@@ -255,7 +255,6 @@\n \t\t\t\u002F\u002F $match[1] is the attribute name, $match[2] is the attribute value including quotes\n \t\t\t$sanitized_name = sanitize_key( $match[1] ); \u002F\u002F Sanitize the attribute name\n \t\t\t$sanitized_value = esc_attr( trim( $match[2], '\"\\'' ) ); \u002F\u002F Remove quotes and escape the value\n-\t\t\t$sanitized_value = str_replace( '\\\\', '', $sanitized_value ); \u002F\u002F Remove quotes and escape the value\n \n \t\t\t\u002F\u002F Reconstruct the attribute\n \t\t\t$sanitized_attrs[] = $sanitized_name . '=\"' . $sanitized_value . '\"';","The attacker requires Contributor or higher privileges to create or edit a WordPress post. \n\n1. Log in to the WordPress dashboard with a Contributor account.\n2. Create a new post or edit an existing one.\n3. Embed the `[eeb_mailto]` shortcode with a malicious payload in the `display` attribute, for example: `[eeb_mailto email=\"attacker@example.com\" display=\"\u003Cimg src=x onerror=alert(document.domain)>\"]`.\n4. Alternatively, use the `extra_attrs` attribute to break out of the HTML tag: `[eeb_mailto email=\"attacker@example.com\" extra_attrs='onmouseover=alert(1)']`.\n5. Save the post. \n6. When an administrator or any other user views the post on the frontend, the plugin's JavaScript decoder (if 'Protect using Javascript' is enabled) will reconstruct the anchor tag with the malicious HTML\u002FJavaScript payload, causing it to execute in the victim's browser context.","gemini-3-flash-preview","2026-04-16 15:21:40","2026-04-16 15:22:18",{"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.4.4","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Femail-encoder-bundle\u002Ftags\u002F2.4.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Femail-encoder-bundle.2.4.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Femail-encoder-bundle\u002Ftags\u002F2.4.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Femail-encoder-bundle.2.4.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Femail-encoder-bundle\u002Ftags"]