[wp-trac] [WordPress Trac] #65270: wp_kses() corrupts valid CSS background-image: url(...) declarations into style=")" 7.0-RC4

WordPress Trac noreply at wordpress.org
Tue May 19 21:06:07 UTC 2026


#65270: wp_kses() corrupts valid CSS background-image: url(...) declarations into
style=")" 7.0-RC4
--------------------------+---------------------
 Reporter:  nextendweb    |       Owner:  (none)
     Type:  defect (bug)  |      Status:  new
 Priority:  normal        |   Milestone:  7.0.1
Component:  Formatting    |     Version:  trunk
 Severity:  normal        |  Resolution:
 Keywords:  needs-patch   |     Focuses:
--------------------------+---------------------

Comment (by dmsnell):

 @nextendweb as unfortunate as it is, I’m glad you found this issue. this
 arose because of the fix you identified in `wp_kses_hair()`, but I don’t
 assess this as a regression. if we go back to the report in the
 description

 {{{#!php
 <?php
 echo wp_kses( '<div style="background-image:
 url("https://localhost/image.jpg");"></div>', $allowed );
 }}}

 this case alone demonstrates the problem in `safecss_filter_attr()`, which
 never handled this valid and common `style` attribute. the root of the
 problem appears to be that `safecss_filter_attr()` assumes it will receive
 decoded HTML values and return decoded HTML values, but `wp_kses_hair()`
 and `wp_kses_attr_check()` are assuming raw and unescaped content.

 the change in 7.0 is that we made `wp_kses_hair()` normalize inputs to
 prevent further breakage downstream, which is a common phenomena in Core.
 to that end, this one particular case will appear as a regression (even
 while many other cases were resolved), but the problem is in the
 interaction of raw and escaped HTML, plus the bigger problem that //we
 can’t split CSS by `;`//. so even if we fix or revert the change to
 `wp_kses_hair()` and bring back the other broken scenarios, we still
 haven’t fixed the bug that broke your code.

 in the meantime, if we want to address this, I think the least harmful
 resolution would be to wrap the call to `safecss_filter_attr()` in
 `wp_kses_attr_check()` so that it escapes and then unescapes the HTML.

 {{{
 diff --git a/src/wp-includes/kses.php b/src/wp-includes/kses.php
 index 062f853085..77c3701a66 100644
 --- a/src/wp-includes/kses.php
 +++ b/src/wp-includes/kses.php
 @@ -1556,7 +1556,8 @@ function wp_kses_attr_check( &$name, &$value,
 &$whole, $vless, $element, $allowe
         }

         if ( 'style' === $name_low ) {
 -               $new_value = safecss_filter_attr( $value );
 +               $decoded_value = WP_HTML_Decoder::decode_attribute( $value
 );
 +               $new_value     = safecss_filter_attr( $decoded_value );

                 if ( empty( $new_value ) ) {
                         $name  = '';
 @@ -1565,7 +1566,7 @@ function wp_kses_attr_check( &$name, &$value,
 &$whole, $vless, $element, $allowe
                         return false;
                 }

 -               $whole = str_replace( $value, $new_value, $whole );
 +               $whole = str_replace( $value, esc_attr( $new_value ),
 $whole );
                 $value = $new_value;
         }

 }}}

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/65270#comment:6>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list