CVE-2010-4536
Description
Multiple cross-site scripting (XSS) vulnerabilities in KSES, as used in WordPress before 3.0.4, allow remote attackers to inject arbitrary web script or HTML via vectors related to (1) the & (ampersand) character, (2) the case of an attribute name, (3) a padded entity, and (4) an entity that is not in normalized form.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
KSES XSS in WordPress before 3.0.4 allows remote attackers to inject arbitrary web script or HTML via malformed HTML entities and attribute vectors.
Vulnerability
KSES, the HTML filtering library used in WordPress, contains multiple cross-site scripting (XSS) vulnerabilities. The flaws arise from improper handling of (1) the & (ampersand) character, (2) the case of attribute names, (3) padded entities, and (4) entities not in normalized form [2]. WordPress versions before 3.0.4 are affected.
Exploitation
An attacker can inject arbitrary web script or HTML by crafting input that bypasses KSES sanitization. No special privileges are required; any vector where user input is processed by KSES (e.g., comments, posts) is exploitable. The attacker sends a request containing one of the malformed entity or attribute vectors to trigger the XSS.
Impact
Successful exploitation allows remote attackers to execute arbitrary JavaScript in the context of a victim's browser. This can lead to session hijacking, content manipulation, or redirection to malicious sites, potentially compromising the affected WordPress site and its users.
Mitigation
The vulnerability is fixed in WordPress version 3.0.4, released on December 20, 2010 [2]. Users should upgrade to this version or later. No workarounds have been published.
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
3cpe:2.3:a:wordpress:wordpress:*:*:*:*:*:*:*:*+ 1 more
- cpe:2.3:a:wordpress:wordpress:*:*:*:*:*:*:*:*range: <=3.0.3
- (no CPE)range: <3.0.4
Patches
15ca8bf6641ebDon't be case sensitive to attribute names. Handle padded entities when checking for bad protocols. Normalize entities before checking for bad protocols in esc_url(). Props Mauro Gentile, duck_, miqrogroove
2 files changed · +14 −28
wp-includes/formatting.php+2 −1 modified@@ -2236,7 +2236,8 @@ function esc_url( $url, $protocols = null, $_context = 'display' ) { // Replace ampersands and single quotes only when displaying. if ( 'display' == $_context ) { - $url = preg_replace('/&([^#])(?![a-z]{2,8};)/', '&$1', $url); + $url = wp_kses_normalize_entities( $url ); + $url = str_replace( '&', '&', $url ); $url = str_replace( "'", ''', $url ); }
wp-includes/kses.php+12 −27 modified@@ -670,7 +670,7 @@ function wp_kses_attr($element, $attr, $allowed_html, $allowed_protocols) { break; } - if ( $arreach['name'] == 'style' ) { + if ( strtolower($arreach['name']) == 'style' ) { $orig_value = $arreach['value']; $value = safecss_filter_attr($orig_value); @@ -762,7 +762,7 @@ function wp_kses_hair($attr, $allowed_protocols) { # "value" { $thisval = $match[1]; - if ( in_array($attrname, $uris) ) + if ( in_array(strtolower($attrname), $uris) ) $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); if(FALSE === array_key_exists($attrname, $attrarr)) { @@ -778,7 +778,7 @@ function wp_kses_hair($attr, $allowed_protocols) { # 'value' { $thisval = $match[1]; - if ( in_array($attrname, $uris) ) + if ( in_array(strtolower($attrname), $uris) ) $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); if(FALSE === array_key_exists($attrname, $attrarr)) { @@ -794,7 +794,7 @@ function wp_kses_hair($attr, $allowed_protocols) { # value { $thisval = $match[1]; - if ( in_array($attrname, $uris) ) + if ( in_array(strtolower($attrname), $uris) ) $thisval = wp_kses_bad_protocol($thisval, $allowed_protocols); if(FALSE === array_key_exists($attrname, $attrarr)) { @@ -1017,14 +1017,9 @@ function wp_kses_html_error($string) { * @return string Sanitized content */ function wp_kses_bad_protocol_once($string, $allowed_protocols) { - global $_kses_allowed_protocols; - $_kses_allowed_protocols = $allowed_protocols; - - $string2 = preg_split('/:|:|:/i', $string, 2); - if ( isset($string2[1]) && !preg_match('%/\?%', $string2[0]) ) - $string = wp_kses_bad_protocol_once2($string2[0]) . trim($string2[1]); - else - $string = preg_replace_callback('/^((&[^;]*;|[\sA-Za-z0-9])*)'.'(:|:|&#[Xx]3[Aa];)\s*/', 'wp_kses_bad_protocol_once2', $string); + $string2 = preg_split( '/:|�*58;|�*3a;/i', $string, 2 ); + if ( isset($string2[1]) && ! preg_match('%/\?%', $string2[0]) ) + $string = wp_kses_bad_protocol_once2( $string2[0], $allowed_protocols ) . trim( $string2[1] ); return $string; } @@ -1038,29 +1033,19 @@ function wp_kses_bad_protocol_once($string, $allowed_protocols) { * @access private * @since 1.0.0 * - * @param mixed $matches string or preg_replace_callback() matches array to check for bad protocols + * @param string $string URI scheme to check against the whitelist + * @param string $allowed_protocols Allowed protocols * @return string Sanitized content */ -function wp_kses_bad_protocol_once2($matches) { - global $_kses_allowed_protocols; - - if ( is_array($matches) ) { - if ( empty($matches[1]) ) - return ''; - - $string = $matches[1]; - } else { - $string = $matches; - } - +function wp_kses_bad_protocol_once2( $string, $allowed_protocols ) { $string2 = wp_kses_decode_entities($string); $string2 = preg_replace('/\s/', '', $string2); $string2 = wp_kses_no_null($string2); $string2 = strtolower($string2); $allowed = false; - foreach ( (array) $_kses_allowed_protocols as $one_protocol) - if (strtolower($one_protocol) == $string2) { + foreach ( (array) $allowed_protocols as $one_protocol ) + if ( strtolower($one_protocol) == $string2 ) { $allowed = true; break; }
Vulnerability mechanics
Root cause
"Missing input normalization (case-insensitive attribute-name checks, entity normalization, and padded-entity handling) in KSES allows protocol-injection and XSS."
Attack vector
An attacker can inject arbitrary script into a WordPress page by supplying a URL or attribute value that uses mixed-case attribute names (e.g. `SRC` instead of `src`) to evade the URI-protocol check [CWE-79]. Additionally, the attacker can pad entity-encoded colons (e.g. `:` or `:`) or use non-normalized entities (e.g. `&#58;`) to hide the colon in a protocol string like `javascript:`, bypassing the protocol whitelist in `esc_url()` and `wp_kses_bad_protocol_once()` [patch_id=1995850]. The crafted input is typically delivered via a comment, post, or other user-submitted content that WordPress filters with KSES.
Affected code
The vulnerability spans two files. In `wp-includes/kses.php`, the `wp_kses_hair()` function did not lowercase attribute names before checking them against a URI list, and `wp_kses_bad_protocol_once()` used an incomplete regex for entity-encoded colons (`:` and `:`), missing padded variants like `�*58;`. In `wp-includes/formatting.php`, `esc_url()` did not normalize HTML entities before replacing ampersands, allowing encoded protocol strings to bypass the protocol whitelist.
What the fix does
The patch addresses four XSS vectors. First, `strtolower()` is added when comparing attribute names in `wp_kses_hair()` and `wp_kses_attr()`, so mixed-case names like `SRC` are correctly recognized as URI attributes [patch_id=1995850]. Second, the regex in `wp_kses_bad_protocol_once()` is updated from `:|:` to `�*58;|�*3a;`, which matches padded zero variants such as `:`. Third, `wp_kses_bad_protocol_once2()` now receives `$allowed_protocols` as a parameter instead of relying on a global variable, improving correctness. Fourth, `esc_url()` in `formatting.php` now calls `wp_kses_normalize_entities()` before replacing ampersands, so double-encoded or non-normalized entities like `&#58;` are decoded to a colon and then caught by the protocol check.
Preconditions
- inputThe attacker must be able to submit content (e.g., a comment or post) that is processed by WordPress's KSES filtering functions.
- configThe target WordPress installation must be running a version prior to 3.0.4.
Generated on May 23, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
10- core.trac.wordpress.org/changeset/17172/branches/3.0nvdPatchVendor Advisory
- wordpress.org/news/2010/12/3-0-4-update/nvdPatchVendor Advisory
- www.openwall.com/lists/oss-security/2010/12/30/1nvdMailing ListPatchThird Party Advisory
- lists.fedoraproject.org/pipermail/package-announce/2011-January/053289.htmlnvdThird Party Advisory
- lists.fedoraproject.org/pipermail/package-announce/2011-January/053293.htmlnvdThird Party Advisory
- secunia.com/advisories/42755nvdThird Party Advisory
- secunia.com/advisories/43000nvdThird Party Advisory
- www.securityfocus.com/bid/45620nvdThird Party AdvisoryVDB Entry
- www.vupen.com/english/advisories/2010/3335nvdThird Party Advisory
- www.vupen.com/english/advisories/2011/0167nvdThird Party Advisory
News mentions
0No linked articles in our index yet.