diff --git a/src/wp-includes/kses.php b/src/wp-includes/kses.php index 2be0b5e14c3cf..7776de59d55d6 100644 --- a/src/wp-includes/kses.php +++ b/src/wp-includes/kses.php @@ -2229,7 +2229,7 @@ function kses_init() { * @since 5.7.1 Added support for `object-position`. * @since 5.8.0 Added support for `calc()` and `var()` values. * @since 6.1.0 Added support for `min()`, `max()`, `minmax()`, `clamp()`, - * and nested `var()` values. + * nested `var()` values, and assigning values to CSS variables. * Added support for `gap`, `column-gap`, `row-gap`, and `flex-wrap`. * Extended `margin-*` and `padding-*` support for logical properties. * @@ -2391,6 +2391,9 @@ function safecss_filter_attr( $css, $deprecated = '' ) { 'object-position', 'overflow', 'vertical-align', + + // Custom CSS properties. + '--*', ) ); @@ -2436,6 +2439,7 @@ function safecss_filter_attr( $css, $deprecated = '' ) { $found = false; $url_attr = false; $gradient_attr = false; + $is_custom_var = false; if ( strpos( $css_item, ':' ) === false ) { $found = true; @@ -2443,11 +2447,23 @@ function safecss_filter_attr( $css, $deprecated = '' ) { $parts = explode( ':', $css_item, 2 ); $css_selector = trim( $parts[0] ); + // Allow assigning values to CSS variables. + if ( in_array( '--*', $allowed_attr, true ) && preg_match( '/^--[a-zA-Z0-9-_]+$/', $css_selector ) ) { + $allowed_attr[] = $css_selector; + $is_custom_var = true; + } + if ( in_array( $css_selector, $allowed_attr, true ) ) { $found = true; $url_attr = in_array( $css_selector, $css_url_data_types, true ); $gradient_attr = in_array( $css_selector, $css_gradient_data_types, true ); } + + if ( $is_custom_var ) { + $css_value = trim( $parts[1] ); + $url_attr = str_starts_with( $css_value, 'url(' ); + $gradient_attr = str_contains( $css_value, '-gradient(' ); + } } if ( $found && $url_attr ) { diff --git a/tests/phpunit/tests/kses.php b/tests/phpunit/tests/kses.php index 274c5aaf7be06..5871f0fe3397f 100644 --- a/tests/phpunit/tests/kses.php +++ b/tests/phpunit/tests/kses.php @@ -1247,6 +1247,23 @@ public function data_test_safecss_filter_attr() { 'css' => 'margin-block-start: 1px;margin-block-end: 2px;margin-inline-start: 3px;margin-inline-end: 4px;padding-block-start: 1px;padding-block-end: 2px;padding-inline-start: 3px;padding-inline-end: 4px', 'expected' => 'margin-block-start: 1px;margin-block-end: 2px;margin-inline-start: 3px;margin-inline-end: 4px;padding-block-start: 1px;padding-block-end: 2px;padding-inline-start: 3px;padding-inline-end: 4px', ), + // Assigning values to CSS variables introduced in 6.1. + array( + 'css' => '--wp--medium-width: 100px; --var_with_underscores: #cccccc;', + 'expected' => '--wp--medium-width: 100px;--var_with_underscores: #cccccc', + ), + array( + 'css' => '--miXeD-CAse: red; --with-numbers-3_56: red; --with-url-value: url("foo.jpg");', + 'expected' => '--miXeD-CAse: red;--with-numbers-3_56: red;--with-url-value: url("foo.jpg")', + ), + array( + 'css' => '--with-gradient: repeating-linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);', + 'expected' => '--with-gradient: repeating-linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)', + ), + array( + 'css' => '--?><.%-not-allowed: red;', + 'expected' => '', + ), ); }