From 8fb143820b2dec1d68454ab2afb90d194d95ea16 Mon Sep 17 00:00:00 2001 From: girishpanchal30 Date: Thu, 20 Aug 2026 17:45:12 +0530 Subject: [PATCH 1/4] fix: enhance color sanitization to handle non-string values --- globals/sanitize-functions.php | 26 +++++++++++++++++++------- tests/test-neve-sanitization.php | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/globals/sanitize-functions.php b/globals/sanitize-functions.php index 47fe9d1489..fb390ff034 100644 --- a/globals/sanitize-functions.php +++ b/globals/sanitize-functions.php @@ -12,11 +12,17 @@ /** * Function to sanitize alpha color. * - * @param string $value Hex or RGBA color. + * @param mixed $value Hex or RGBA color. * * @return string */ function neve_sanitize_colors( $value ) { + if ( ! is_string( $value ) && ! is_numeric( $value ) ) { + return ''; + } + + $value = (string) $value; + $is_var = ( strpos( $value, 'var' ) !== false ); if ( $is_var ) { @@ -31,19 +37,25 @@ function neve_sanitize_colors( $value ) { $mode = ( false === strpos( $value, 'rgba' ) ) ? 'hex' : 'rgba'; if ( 'rgba' === $mode ) { return neve_sanitize_rgba( $value ); - } else { - return sanitize_hex_color( $value ); } + + $hex_color = sanitize_hex_color( $value ); + + return null === $hex_color ? '' : $hex_color; } /** * Sanitize rgba color. * - * @param string $value Color in rgba format. + * @param mixed $value Color in rgba format. * * @return string */ function neve_sanitize_rgba( $value ) { + if ( ! is_string( $value ) ) { + return 'rgba(0,0,0,0)'; + } + $red = 'rgba(0,0,0,0)'; $green = 'rgba(0,0,0,0)'; $blue = 'rgba(0,0,0,0)'; @@ -165,9 +177,9 @@ function neve_sanitize_background( $value ) { } - $value['imageUrl'] = esc_url( $value['imageUrl'] ); - $value['colorValue'] = neve_sanitize_colors( $value['colorValue'] ); - $value['overlayColorValue'] = neve_sanitize_colors( $value['overlayColorValue'] ); + $value['imageUrl'] = esc_url( isset( $value['imageUrl'] ) ? $value['imageUrl'] : '' ); + $value['colorValue'] = neve_sanitize_colors( isset( $value['colorValue'] ) ? $value['colorValue'] : '' ); + $value['overlayColorValue'] = neve_sanitize_colors( isset( $value['overlayColorValue'] ) ? $value['overlayColorValue'] : '' ); $value['overlayOpacity'] = (int) $value['overlayOpacity']; diff --git a/tests/test-neve-sanitization.php b/tests/test-neve-sanitization.php index fbd32d8958..a0ff9cedda 100644 --- a/tests/test-neve-sanitization.php +++ b/tests/test-neve-sanitization.php @@ -134,6 +134,29 @@ public function test_sanitize_responsive_int_json() { $this->do_assertion_for_sanitize_responsive_int_json( $input_value, $expected_value ); } + /** + * Test that color sanitization does not fatal on array or non-string values. + */ + public function test_sanitize_colors_with_non_string_values() { + $this->assertSame( '', neve_sanitize_colors( [ '#ffffff', '#000000' ] ) ); + $this->assertSame( '', neve_sanitize_colors( [ 'mobile' => '#ffffff' ] ) ); + $this->assertSame( '', neve_sanitize_colors( [] ) ); + + // Other non-color values are rejected too. + $this->assertSame( '', neve_sanitize_colors( null ) ); + $this->assertSame( '', neve_sanitize_colors( true ) ); + $this->assertSame( '', neve_sanitize_colors( new stdClass() ) ); + + // Invalid strings return an empty string, never null. + $this->assertSame( '', neve_sanitize_colors( 'not-a-color' ) ); + $this->assertSame( '', neve_sanitize_colors( '' ) ); + + // Valid values keep working as before. + $this->assertSame( '#ff0000', neve_sanitize_colors( '#ff0000' ) ); + $this->assertSame( 'rgba(255,0,0,1)', neve_sanitize_colors( 'rgba(255, 0, 0, 1)' ) ); + $this->assertSame( 'var(--nv-primary-accent)', neve_sanitize_colors( 'var(--nv-primary-accent)' ) ); + } + /** * Private reusable function for the assertion of sanitize responsive int json. * From 40c16d1dece58357321dcfbf3354e9d32b30e241 Mon Sep 17 00:00:00 2001 From: girishpanchal30 Date: Thu, 20 Aug 2026 18:08:43 +0530 Subject: [PATCH 2/4] fix: ensure overlay opacity is set --- globals/sanitize-functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/globals/sanitize-functions.php b/globals/sanitize-functions.php index fb390ff034..abb3c3f4e8 100644 --- a/globals/sanitize-functions.php +++ b/globals/sanitize-functions.php @@ -182,7 +182,7 @@ function neve_sanitize_background( $value ) { $value['overlayColorValue'] = neve_sanitize_colors( isset( $value['overlayColorValue'] ) ? $value['overlayColorValue'] : '' ); - $value['overlayOpacity'] = (int) $value['overlayOpacity']; + $value['overlayOpacity'] = isset( $value['overlayOpacity'] ) ? (int) $value['overlayOpacity'] : 0; if ( $value['overlayOpacity'] > 100 || $value['overlayOpacity'] < 0 ) { $value['overlayOpacity'] = 50; } From d0331db74e9e9f945ac4bcf070dcf3019679c13f Mon Sep 17 00:00:00 2001 From: girishpanchal30 Date: Thu, 20 Aug 2026 18:37:50 +0530 Subject: [PATCH 3/4] fix: enhance color sanitization --- globals/sanitize-functions.php | 27 ++++++++++++--- tests/test-neve-sanitization.php | 59 ++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/globals/sanitize-functions.php b/globals/sanitize-functions.php index abb3c3f4e8..2047e603af 100644 --- a/globals/sanitize-functions.php +++ b/globals/sanitize-functions.php @@ -9,6 +9,27 @@ * @package Neve\Globals */ +/** + * Check whether a value is a well formed CSS variable expression. + * + * @param mixed $value Value to check. + * + * @return bool + */ +function neve_is_css_var( $value ) { + if ( ! is_string( $value ) ) { + return false; + } + + $hex = '#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})'; + $color_fn = '(?:rgb|rgba|hsl|hsla)\(\s*[0-9a-z.,%\/\s-]+\)'; + $keyword = '[a-z]+(?:-[a-z]+)*'; + $fallback = '(?:(?P>nv_var)|' . $hex . '|' . $color_fn . '|' . $keyword . ')'; + $pattern = '/^(?Pvar\(\s*--[a-z0-9_-]+\s*(?:,\s*' . $fallback . '\s*)?\))$/i'; + + return (bool) preg_match( $pattern, trim( $value ) ); +} + /** * Function to sanitize alpha color. * @@ -23,10 +44,8 @@ function neve_sanitize_colors( $value ) { $value = (string) $value; - $is_var = ( strpos( $value, 'var' ) !== false ); - - if ( $is_var ) { - return sanitize_text_field( $value ); + if ( neve_is_css_var( $value ) ) { + return trim( $value ); } if ( false !== strpos( $value, 'gradient' ) ) { diff --git a/tests/test-neve-sanitization.php b/tests/test-neve-sanitization.php index a0ff9cedda..5281d25bea 100644 --- a/tests/test-neve-sanitization.php +++ b/tests/test-neve-sanitization.php @@ -157,6 +157,65 @@ public function test_sanitize_colors_with_non_string_values() { $this->assertSame( 'var(--nv-primary-accent)', neve_sanitize_colors( 'var(--nv-primary-accent)' ) ); } + /** + * Test that only well formed CSS variable expressions are treated as CSS variables. + */ + public function test_is_css_var() { + $valid = [ + 'var(--nv-primary-accent)', + 'var(--nv-c-1,#E5E7EB)', + 'var(--nv-c-1, #e5e7eb)', + 'var( --nv-site-bg , #fff )', + 'var(--secondarybtnbg, transparent)', + 'var(--x, rgba(0,0,0,.5))', + 'var(--x, hsl(120 50% 50%))', + 'var(--x, var(--y, #fff))', + ]; + + foreach ( $valid as $value ) { + $this->assertTrue( neve_is_css_var( $value ), $value . ' should be a CSS var' ); + } + + $invalid = [ + 'avatar', + 'varsity', + '#var', + 'var', + 'var()', + 'var(--)', + 'var(--x', + 'var(--x))', + 'var(--x);color:red', + 'var(--x)}body{background:red}', + 'var(--x, url(evil.css))', + 'var(--x, "quoted")', + 'linear-gradient(var(--a), var(--b))', + '', + [ 'var(--x)' ], + null, + ]; + + foreach ( $invalid as $value ) { + $this->assertFalse( neve_is_css_var( $value ), var_export( $value, true ) . ' should not be a CSS var' ); + } + } + + /** + * Test that color sanitization does not pass off arbitrary strings as CSS variables. + */ + public function test_sanitize_colors_rejects_fake_css_vars() { + // Strings that merely contain "var" are not CSS variables. + $this->assertSame( '', neve_sanitize_colors( 'avatar' ) ); + $this->assertSame( '', neve_sanitize_colors( 'var(--x);color:red' ) ); + $this->assertSame( '', neve_sanitize_colors( 'var(--x)}body{background:red}' ) ); + $this->assertSame( '', neve_sanitize_colors( 'var(--x, url(evil.css))' ) ); + + // Well formed CSS variables pass through untouched. + $this->assertSame( 'var(--nv-site-bg)', neve_sanitize_colors( 'var(--nv-site-bg)' ) ); + $this->assertSame( 'var(--nv-c-1, #e5e7eb)', neve_sanitize_colors( ' var(--nv-c-1, #e5e7eb) ' ) ); + $this->assertSame( 'var(--x, var(--y, #fff))', neve_sanitize_colors( 'var(--x, var(--y, #fff))' ) ); + } + /** * Private reusable function for the assertion of sanitize responsive int json. * From 82b3b0417b80161ed096bb35fdb7091d0a33cc25 Mon Sep 17 00:00:00 2001 From: girishpanchal30 Date: Thu, 20 Aug 2026 18:54:58 +0530 Subject: [PATCH 4/4] fix: sanitize color control values --- globals/sanitize-functions.php | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/globals/sanitize-functions.php b/globals/sanitize-functions.php index 2047e603af..c2143336b0 100644 --- a/globals/sanitize-functions.php +++ b/globals/sanitize-functions.php @@ -21,19 +21,25 @@ function neve_is_css_var( $value ) { return false; } + $value = trim( $value ); + + if ( $value === '' || strlen( $value ) > 200 ) { + return false; + } + $hex = '#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})'; $color_fn = '(?:rgb|rgba|hsl|hsla)\(\s*[0-9a-z.,%\/\s-]+\)'; $keyword = '[a-z]+(?:-[a-z]+)*'; $fallback = '(?:(?P>nv_var)|' . $hex . '|' . $color_fn . '|' . $keyword . ')'; $pattern = '/^(?Pvar\(\s*--[a-z0-9_-]+\s*(?:,\s*' . $fallback . '\s*)?\))$/i'; - return (bool) preg_match( $pattern, trim( $value ) ); + return (bool) preg_match( $pattern, $value ); } /** - * Function to sanitize alpha color. + * Sanitize a color control value. * - * @param mixed $value Hex or RGBA color. + * @param mixed $value Color value: CSS variable, gradient, rgba() or hex. * * @return string */ @@ -196,18 +202,17 @@ function neve_sanitize_background( $value ) { } - $value['imageUrl'] = esc_url( isset( $value['imageUrl'] ) ? $value['imageUrl'] : '' ); - $value['colorValue'] = neve_sanitize_colors( isset( $value['colorValue'] ) ? $value['colorValue'] : '' ); - $value['overlayColorValue'] = neve_sanitize_colors( isset( $value['overlayColorValue'] ) ? $value['overlayColorValue'] : '' ); - + $value['imageUrl'] = esc_url( $value['imageUrl'] ?? '' ); + $value['colorValue'] = neve_sanitize_colors( $value['colorValue'] ?? '' ); + $value['overlayColorValue'] = neve_sanitize_colors( $value['overlayColorValue'] ?? '' ); - $value['overlayOpacity'] = isset( $value['overlayOpacity'] ) ? (int) $value['overlayOpacity'] : 0; + $value['overlayOpacity'] = (int) ( $value['overlayOpacity'] ?? 0 ); if ( $value['overlayOpacity'] > 100 || $value['overlayOpacity'] < 0 ) { $value['overlayOpacity'] = 50; } - $value['fixed'] = (bool) $value['fixed']; - $value['useFeatured'] = (bool) $value['useFeatured']; + $value['fixed'] = (bool) ( $value['fixed'] ?? false ); + $value['useFeatured'] = (bool) ( $value['useFeatured'] ?? false ); return $value; }