From fa96d5931826b936095022013e30ee5934018779 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 2 Jun 2020 23:44:40 +0000 Subject: [PATCH] Formatting: add a new 'safe_style_disallowed_chars' filter. Enable developers to change the regex used in `safecss_filter_attr` to limit characters in the parsed CSS. Props paulschreiber, swissspidy, rmccue, bartekcholewa, miinasikk. Fixes #37134. git-svn-id: https://develop.svn.wordpress.org/trunk@47891 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/kses.php | 23 ++++++--- tests/phpunit/tests/kses.php | 95 +++++++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/src/wp-includes/kses.php b/src/wp-includes/kses.php index 1aace6c4fa..f1372fbd52 100644 --- a/src/wp-includes/kses.php +++ b/src/wp-includes/kses.php @@ -2301,13 +2301,24 @@ function safecss_filter_attr( $css, $deprecated = '' ) { } } - // Remove any CSS containing containing \ ( & } = or comments, except for url() useage checked above. - if ( $found && ! preg_match( '%[\\\(&=}]|/\*%', $css_test_string ) ) { - if ( '' !== $css ) { - $css .= ';'; + if ( $found ) { + /** + * Filters the regex limiting the list of characters not allowed in CSS rules. + * + * Default behaviour is to remove any css containing \ ( & } = or comments, except for url() usage. + * + * @since 5.5.0 + * + * @param string $regex Regex pattern of disallowed characters in CSS rules. Default is '%[\\\(&=}]|/\*%'. + * @param string $css_test_string CSS value to test. + */ + $disallowed_chars = apply_filters( 'safe_style_disallowed_chars', '%[\\\(&=}]|/\*%', $css_test_string ); + if ( ! preg_match( $disallowed_chars, $css_test_string ) ) { + if ( '' !== $css ) { + $css .= ';'; + } + $css .= $css_item; } - - $css .= $css_item; } } diff --git a/tests/phpunit/tests/kses.php b/tests/phpunit/tests/kses.php index ab675abbc3..7a846d5292 100644 --- a/tests/phpunit/tests/kses.php +++ b/tests/phpunit/tests/kses.php @@ -1002,7 +1002,21 @@ EOF; 'css' => 'background: conic-gradient(at 0% 30%, red 10%, yellow 30%, #1e90ff 50%)', 'expected' => 'background: conic-gradient(at 0% 30%, red 10%, yellow 30%, #1e90ff 50%)', ), - + // Expressions are not allowed. + array( + 'css' => 'height: expression( body.scrollTop + 50 + "px" )', + 'expected' => '', + ), + // RGB color values are not allowed. + array( + 'css' => 'color: rgb( 100, 100, 100 )', + 'expected' => '', + ), + // RGBA color values are not allowed. + array( + 'css' => 'color: rgb( 100, 100, 100, .4 )', + 'expected' => '', + ), ); } @@ -1247,4 +1261,83 @@ EOF; ), ); } + + /** + * Filter for disallowed characters never matches thus allowing all characters. + */ + function _safe_style_disallowed_chars_filter( $regex ) { + return '%a^%'; // Regex with no matches. + + } + /** + * Testing the safecss_filter_attr() function with the safe_style_disallowed_chars filter. + * + * @ticket 37134 + * + * @dataProvider data_test_safecss_filter_attr_filtered + * + * @param string $css A string of CSS rules. + * @param string $expected Expected string of CSS rules. + */ + public function test_safecss_filter_attr_filtered( $css, $expected ) { + add_filter( 'safe_style_disallowed_chars', array( $this, '_safe_style_disallowed_chars_filter' ) ); + $this->assertSame( $expected, safecss_filter_attr( $css ) ); + remove_filter( 'safe_style_disallowed_chars', array( $this, '_safe_style_disallowed_chars_filter' ) ); + } + + /** + * Data Provider for test_safecss_filter_attr_filtered(). + * + * @return array { + * @type array { + * @string string $css A string of CSS rules. + * @string string $expected Expected string of CSS rules. + * } + * } + */ + public function data_test_safecss_filter_attr_filtered() { + return array( + + // A single attribute name, with a single value. + array( + 'css' => 'margin-top: 2px', + 'expected' => 'margin-top: 2px', + ), + // Backslash \ can be allowed with the 'safe_style_disallowed_chars' filter. + array( + 'css' => 'margin-top: \2px', + 'expected' => 'margin-top: \2px', + ), + // Curly bracket } can be allowed with the 'safe_style_disallowed_chars' filter. + array( + 'css' => 'margin-bottom: 2px}', + 'expected' => 'margin-bottom: 2px}', + ), + // Parenthesis ) can be allowed with the 'safe_style_disallowed_chars' filter. + array( + 'css' => 'margin-bottom: 2px)', + 'expected' => 'margin-bottom: 2px)', + ), + // Ampersand & can be allowed with the 'safe_style_disallowed_chars' filter. + array( + 'css' => 'margin-bottom: 2px&', + 'expected' => 'margin-bottom: 2px&', + ), + // Expressions can be allowed with the 'safe_style_disallowed_chars' filter. + array( + 'css' => 'height: expression( body.scrollTop + 50 + "px" )', + 'expected' => 'height: expression( body.scrollTop + 50 + "px" )', + ), + // RGB color values can be allowed with the 'safe_style_disallowed_chars' filter. + array( + 'css' => 'color: rgb( 100, 100, 100 )', + 'expected' => 'color: rgb( 100, 100, 100 )', + ), + // RGBA color values can be allowed with the 'safe_style_disallowed_chars' filter. + array( + 'css' => 'color: rgb( 100, 100, 100, .4 )', + 'expected' => 'color: rgb( 100, 100, 100, .4 )', + ), + ); + } }