Skip to content

Commit

Permalink
Section Styles: Fix insecure properties removal for inner block types…
Browse files Browse the repository at this point in the history
… and elements
  • Loading branch information
aaronrobertshaw committed Nov 11, 2024
1 parent 55913fe commit 35dcba4
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 19 deletions.
77 changes: 58 additions & 19 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -3565,26 +3565,12 @@ public static function remove_insecure_properties( $theme_json, $origin = 'theme

$variation_output = static::remove_insecure_styles( $variation_input );

// Process a variation's elements and element pseudo selector styles.
if ( isset( $variation_input['elements'] ) ) {
foreach ( $valid_element_names as $element_name ) {
$element_input = $variation_input['elements'][ $element_name ] ?? null;
if ( $element_input ) {
$element_output = static::remove_insecure_styles( $element_input );

if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) {
foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) {
if ( isset( $element_input[ $pseudo_selector ] ) ) {
$element_output[ $pseudo_selector ] = static::remove_insecure_styles( $element_input[ $pseudo_selector ] );
}
}
}
if ( isset( $variation_input['blocks'] ) ) {
$variation_output['blocks'] = static::remove_insecure_inner_block_styles( $variation_input['blocks'], $blocks_metadata );
}

if ( ! empty( $element_output ) ) {
_wp_array_set( $variation_output, array( 'elements', $element_name ), $element_output );
}
}
}
if ( isset( $variation_input['elements'] ) ) {
$variation_output['elements'] = static::remove_insecure_element_styles( $variation_input['elements'] );
}

if ( ! empty( $variation_output ) ) {
Expand Down Expand Up @@ -3622,6 +3608,59 @@ public static function remove_insecure_properties( $theme_json, $origin = 'theme
return $theme_json;
}

/**
* Remove insecure element styles within a variation or block.
*
* @since 6.8.0
*
* @param array $elements The elements to process.
* @return array The sanitized elements styles.
*/
protected static function remove_insecure_element_styles( $elements ) {
$sanitized = array();
$valid_element_names = array_keys( static::ELEMENTS );

foreach ( $valid_element_names as $element_name ) {
$element_input = $elements[ $element_name ] ?? null;
if ( $element_input ) {
$element_output = static::remove_insecure_styles( $element_input );

if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) {
foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) {
if ( isset( $element_input[ $pseudo_selector ] ) ) {
$element_output[ $pseudo_selector ] = static::remove_insecure_styles( $element_input[ $pseudo_selector ] );
}
}
}

$sanitized[ $element_name ] = $element_output;
}
}
return $sanitized;
}

/**
* Remove insecure styles from inner blocks and their elements.
*
* @since 6.8.0
*
* @param array $blocks The block styles to process.
* @return array Sanitized block type styles.
*/
protected static function remove_insecure_inner_block_styles( $blocks ) {
$sanitized = array();
foreach ( $blocks as $block_type => $block_input ) {
$block_output = static::remove_insecure_styles( $block_input );

if ( isset( $block_input['elements'] ) ) {
$block_output['elements'] = static::remove_insecure_element_styles( $block_input['elements'] );
}

$sanitized[ $block_type ] = $block_output;
}
return $sanitized;
}

/**
* Processes a setting node and returns the same node
* without the insecure settings.
Expand Down
173 changes: 173 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -4387,6 +4387,179 @@ public function test_block_style_variations_with_invalid_properties() {
$this->assertSameSetsWithIndex( $expected, $actual );
}

public function test_block_style_variations_with_inner_blocks_and_elements() {
wp_set_current_user( static::$administrator_id );
gutenberg_register_block_style(
array( 'core/group' ),
array(
'name' => 'custom-group',
'label' => 'Custom Group',
)
);

$expected = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'blocks' => array(
'core/group' => array(
'color' => array(
'background' => 'blue',
),
'variations' => array(
'custom-group' => array(
'color' => array(
'background' => 'purple',
),
'blocks' => array(
'core/paragraph' => array(
'color' => array(
'text' => 'red',
),
'elements' => array(
'link' => array(
'color' => array(
'text' => 'blue',
),
':hover' => array(
'color' => array(
'text' => 'green',
),
),
),
),
),
'core/heading' => array(
'typography' => array(
'fontSize' => '24px',
),
),
),
'elements' => array(
'link' => array(
'color' => array(
'text' => 'yellow',
),
':hover' => array(
'color' => array(
'text' => 'orange',
),
),
),
),
),
),
),
),
),
);

$actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( $expected );

// The sanitization processes blocks in a specific order which might differ to the theme.json input.
$this->assertEqualsCanonicalizing(
$expected,
$actual,
'Block style variations data does not match when inner blocks or element styles present'
);
}

public function test_block_style_variations_with_invalid_inner_block_or_element_styles() {
wp_set_current_user( static::$administrator_id );
gutenberg_register_block_style(
array( 'core/group' ),
array(
'name' => 'custom-group',
'label' => 'Custom Group',
)
);

$input = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'blocks' => array(
'core/group' => array(
'variations' => array(
'custom-group' => array(
'blocks' => array(
'core/paragraph' => array(
'color' => array(
'text' => 'red',
),
'typography' => array(
'fontSize' => 'alert(1)', // Should be removed.
),
'elements' => array(
'link' => array(
'color' => array(
'text' => 'blue',
),
'css' => 'unsafe-value', // Should be removed.
),
),
'custom' => 'unsafe-value', // Should be removed.
),
),
'elements' => array(
'link' => array(
'color' => array(
'text' => 'yellow',
),
'javascript' => 'alert(1)', // Should be removed.
),
),
),
),
),
),
),
);

$expected = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'blocks' => array(
'core/group' => array(
'variations' => array(
'custom-group' => array(
'blocks' => array(
'core/paragraph' => array(
'color' => array(
'text' => 'red',
),
'elements' => array(
'link' => array(
'color' => array(
'text' => 'blue',
),
),
),
),
),
'elements' => array(
'link' => array(
'color' => array(
'text' => 'yellow',
),
),
),
),
),
),
),
),
);

$actual = WP_Theme_JSON_Gutenberg::remove_insecure_properties( $input );

// The sanitization processes blocks in a specific order which might differ to the theme.json input.
$this->assertEqualsCanonicalizing(
$expected,
$actual,
'Insecure properties were not removed from block style variation inner block types or elements'
);
}


/**
* Tests generating the spacing presets array based on the spacing scale provided.
*
Expand Down

0 comments on commit 35dcba4

Please sign in to comment.