SECURITY ADVISORY / 01

CVE-2025-13387 Exploit & Vulnerability Analysis

Complete CVE-2025-13387 security advisory with proof of concept (PoC), exploit details, and patch analysis for kadence-woocommerce-email-designer.

kadence-woocommerce-email-designer products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An unauthenticated attacker can inject arbitrary JavaScript into WooCommerce email designer preview pages by crafting a malicious customer name during checkout. The payload is stored in the WooCommerce order object and executed whenever any user (including administrators) views the order via the Kadence plugin's preview or email rendering functionality.

POST /wp-json/wc/v3/orders HTTP/1.1
Host: target-wordpress.local
Content-Type: application/json

{
  "billing": {
    "first_name": "\"; alert('XSS'); var x=\"",
    "last_name": "Test"
  }
}

When an administrator or customer views the order in the Kadence email designer, the injected JavaScript executes in their browser context. The attacker observes the alert box firing, confirming script execution. More critically, the payload executes within the admin panel, allowing theft of session cookies, CSRF token manipulation, or silent redirection to a credential harvesting page.

What the Patch Did

Before

$scripts .= 'var pl_customer_first_name = "' . self::$current_order->get_billing_first_name() . '";';
$scripts .= 'var pl_customer_last_name = "' . self::$current_order->get_billing_last_name() . '";';
$scripts .= 'var pl_customer_full_name = "' . self::$current_order->get_formatted_billing_full_name() . '";';
$scripts .= 'var pl_customer_username = "' . Kadence_Woomail_Designer::get_username_from_id( $user_id ) . '";';

After

$scripts .= 'var pl_customer_first_name = "' . esc_js(self::$current_order->get_billing_first_name()) . '";';
$scripts .= 'var pl_customer_last_name = "' . esc_js(self::$current_order->get_billing_last_name()) . '";';
$scripts .= 'var pl_customer_full_name = "' . esc_js(self::$current_order->get_formatted_billing_full_name()) . '";';
$scripts .= 'var pl_customer_username = "' . esc_js( Kadence_Woomail_Designer::get_username_from_id( $user_id ) ) . '";';

The patch applied WordPress's esc_js() output escaping function to all dynamic values before concatenating them into JavaScript string literals. This function escapes characters with special meaning in JavaScript context—primarily quotes, backslashes, and newlines—preventing an attacker's quote characters from breaking out of the string and injecting arbitrary code. The security control is output escaping at the JavaScript sink, enforced by the esc_js() API.

Root Cause

This is Stored Cross-Site Scripting (CWE-79). Attacker-controlled data enters the system through WooCommerce order fields (billing first name, last name, formatted full name, and username) during checkout or order creation. These values flow from the database into class-kadence-woomail-preview.php lines 882–891 via WooCommerce getter methods like get_billing_first_name(). The code concatenates this untrusted data directly into a JavaScript string literal without escaping, crossing a trust boundary from the data tier into executable code context. When the email preview is rendered, the browser parses the malicious payload as JavaScript and executes it under the privileges of the logged-in administrator.

Why It Works

The load-bearing line is esc_js(self::$current_order->get_billing_first_name()). Without this single escaping function, an attacker's quote character (") terminates the string, and arbitrary JavaScript follows. With esc_js() applied, quotes are converted to escape sequences (\") that are rendered as literal characters within the string, not as syntax. The engineer wrapped all four name/username variables identically because each one is concatenated into a JavaScript string literal in the same pattern: var pl_customer_X = " + untrusted_data + ". Omitting esc_js() from even one variable (e.g., just the username) would leave the bug exploitable via that single unescaped sink.

Hardening Checklist

  • Apply output escaping context-specifically: Always use esc_attr() for HTML attributes, esc_js() for JavaScript strings, esc_html() for HTML body content, and wp_json_encode() for JSON. Never trust that data is "safe" before escaping—escaping must occur at the sink, not at storage.

  • Audit all template variable concatenation: Search the codebase for patterns like '... "' . $var . '"' and '... \'' . $var . '\'' in JavaScript and attribute contexts. These are high-risk concatenation patterns that demand immediate escaping review.

  • Use static analysis for XSS detection: Integrate WordPress linting tools such as wp-cli --since=5.0 lint or third-party SAST tools (e.g., SonarQube, Semgrep with WordPress rules) into CI/CD to catch unescaped variable output before release.

  • Sanitize at input; escape at output: Even though this vulnerability was ultimately an escaping failure, implement sanitize_text_field() on order metadata at the API boundary to prevent unexpectedly malicious characters from entering the database in the first place.

  • Test with payload-bearing fixtures: Create automated tests that include customer names containing quotes, backslashes, and newlines, then verify the rendered JavaScript parses without syntax errors and does not execute injected code.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2025-13387

Frequently asked questions about CVE-2025-13387

What is CVE-2025-13387?

CVE-2025-13387 is a security vulnerability identified in kadence-woocommerce-email-designer. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2025-13387?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2025-13387. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2025-13387 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting kadence-woocommerce-email-designer. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2025-13387?

CVE-2025-13387 affects kadence-woocommerce-email-designer. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2025-13387?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for kadence-woocommerce-email-designer.

What is the CVSS score for CVE-2025-13387?

The severity rating and CVSS scoring for CVE-2025-13387 affecting kadence-woocommerce-email-designer is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.