[wp-trac] [WordPress Trac] #64418: Valid CSS is causing failure in the Additional CSS panel

WordPress Trac noreply at wordpress.org
Thu Dec 18 18:48:49 UTC 2025


#64418: Valid CSS is causing failure in the Additional CSS panel
--------------------------+-------------------------
 Reporter:  drw158        |       Owner:  jonsurrell
     Type:  defect (bug)  |      Status:  assigned
 Priority:  normal        |   Milestone:  7.0
Component:  Customize     |     Version:  4.7
 Severity:  normal        |  Resolution:
 Keywords:  has-patch     |     Focuses:  css
--------------------------+-------------------------

Comment (by westonruter):

 Replying to [comment:11 westonruter]:
 > @dmsnell @jonsurrell I'm not sure that KSES applies here? The
 `wp_custom_css_cb()` function outputs the CSS without KSES. It just uses
 `strip_tags()`.

 Actually, after looking at #38715, I am reminded that KSES may actually be
 a problem here. It's not that that we need to fix KSES but rather to
 prevent KSES from running in the first place.

 For the Customizer's Custom CSS, the CSS is stored in a `custom_css` CPT
 via `wp_update_custom_css_post()` which does:

 {{{#!php
 <?php
 $r = wp_insert_post( wp_slash( $post_data ), true );
 }}}

 This means if a user can't do `unfiltered_html`, the data will get
 sanitized with KSES.

 I believe we need a workaround similar to what was done in
 `WP_Customize_Manager::save_changeset_post()` for storing Customizer
 changesets (the `customize_changeset` CPT) where it wraps the call to
 `wp_update_post()` as follows:

 {{{#!php
 <?php
 add_filter( 'wp_insert_post_data', array( $this,
 'preserve_insert_changeset_post_content' ), 5, 3 );
 // ...
 $r = wp_update_post( wp_slash( $post_array ), true );
 // ...
 remove_filter( 'wp_insert_post_data', array( $this,
 'preserve_insert_changeset_post_content' ), 5 );
 }}}

 The `WP_Customize_Manager::preserve_insert_changeset_post_content()`
 method looks like this:

 {{{#!php
 <?php
         public function preserve_insert_changeset_post_content( $data,
 $postarr, $unsanitized_postarr ) {
                 if (
                         isset( $data['post_type'] ) &&
                         isset( $unsanitized_postarr['post_content'] ) &&
                         'customize_changeset' === $data['post_type'] ||
                         (
                                 'revision' === $data['post_type'] &&
                                 ! empty( $data['post_parent'] ) &&
                                 'customize_changeset' === get_post_type(
 $data['post_parent'] )
                         )
                 ) {
                         $data['post_content'] =
 $unsanitized_postarr['post_content'];
                 }
                 return $data;
         }
 }}}

 It's ugly, but it bypasses KSES corruption. It also prevents other plugins
 from corrupting the JSON stored in the `post_content` in arbitrary ways,
 which I recall being the added benefit to this approach. Otherwise, this
 could seem to be achieved via:

 {{{#!php
 <?php
 $priority = has_filter( 'content_save_pre', 'wp_filter_post_kses' );
 if ( false !== $priority ) {
     remove_filter( 'content_save_pre', 'wp_filter_post_kses', $priority );
 }
 $r = wp_update_post( wp_slash( $post_array ), true );
 if ( false !== $priority ) {
     add_filter( 'content_save_pre', 'wp_filter_post_kses', $priority );
 }
 }}}

 I see this is also the case for the `wp_global_styles` CPT in addition to
 `custom_css`. Note how `WP_Theme_JSON_Resolver::get_user_data()` somewhat
 anticipates this by checking for JSON decoding errors. It doesn't seem
 that `WP_REST_Global_Styles_Controller` is doing anything to prevent KSES
 from applying. In contrast, `kses_init_filters()` actually adds a filter
 specifically for `wp_global_styles`:

 {{{#!php
 <?php
 // Global Styles filtering: Global Styles filters should be executed
 before normal post_kses HTML filters.
 add_filter( 'content_save_pre', 'wp_filter_global_styles_post', 9 );
 add_filter( 'content_filtered_save_pre', 'wp_filter_global_styles_post', 9
 );
 }}}

 Note that I can't seem to access Additional CSS in the Site Editor when
 `DISALLOW_UNFILTERED_HTML` is enabled, so this KSES issue may not be
 relevant here.

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


More information about the wp-trac mailing list