Make WordPress Core

Changeset 59802


Ignore:
Timestamp:
02/10/2025 10:27:49 PM (18 months ago)
Author:
peterwilsoncc
Message:

Global Styles: Improve sanitization of block variation styles.

Fixes an issue where block style variations containing inner block type and element styles would have those inner styles stripped when the user attempting to save Global Styles does not have the unfiltered_html capability.

Props aaronrobertshaw, mukesh27, andrewserong.
Fixes #62372.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-theme-json.php

    r59499 r59802  
    35533553                                        $variation_output = static::remove_insecure_styles( $variation_input );
    35543554
    3555                                         // Process a variation's elements and element pseudo selector styles.
     3555                                        if ( isset( $variation_input['blocks'] ) ) {
     3556                                                $variation_output['blocks'] = static::remove_insecure_inner_block_styles( $variation_input['blocks'] );
     3557                                        }
     3558
    35563559                                        if ( isset( $variation_input['elements'] ) ) {
    3557                                                 foreach ( $valid_element_names as $element_name ) {
    3558                                                         $element_input = $variation_input['elements'][ $element_name ] ?? null;
    3559                                                         if ( $element_input ) {
    3560                                                                 $element_output = static::remove_insecure_styles( $element_input );
    3561 
    3562                                                                 if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) {
    3563                                                                         foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) {
    3564                                                                                 if ( isset( $element_input[ $pseudo_selector ] ) ) {
    3565                                                                                         $element_output[ $pseudo_selector ] = static::remove_insecure_styles( $element_input[ $pseudo_selector ] );
    3566                                                                                 }
    3567                                                                         }
    3568                                                                 }
    3569 
    3570                                                                 if ( ! empty( $element_output ) ) {
    3571                                                                         _wp_array_set( $variation_output, array( 'elements', $element_name ), $element_output );
    3572                                                                 }
    3573                                                         }
    3574                                                 }
     3560                                                $variation_output['elements'] = static::remove_insecure_element_styles( $variation_input['elements'] );
    35753561                                        }
    35763562
     
    36083594
    36093595                return $theme_json;
     3596        }
     3597
     3598        /**
     3599         * Remove insecure element styles within a variation or block.
     3600         *
     3601         * @since 6.8.0
     3602         *
     3603         * @param array $elements The elements to process.
     3604         * @return array The sanitized elements styles.
     3605         */
     3606        protected static function remove_insecure_element_styles( $elements ) {
     3607                $sanitized           = array();
     3608                $valid_element_names = array_keys( static::ELEMENTS );
     3609
     3610                foreach ( $valid_element_names as $element_name ) {
     3611                        $element_input = $elements[ $element_name ] ?? null;
     3612                        if ( $element_input ) {
     3613                                $element_output = static::remove_insecure_styles( $element_input );
     3614
     3615                                if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) {
     3616                                        foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) {
     3617                                                if ( isset( $element_input[ $pseudo_selector ] ) ) {
     3618                                                        $element_output[ $pseudo_selector ] = static::remove_insecure_styles( $element_input[ $pseudo_selector ] );
     3619                                                }
     3620                                        }
     3621                                }
     3622
     3623                                $sanitized[ $element_name ] = $element_output;
     3624                        }
     3625                }
     3626                return $sanitized;
     3627        }
     3628
     3629        /**
     3630         * Remove insecure styles from inner blocks and their elements.
     3631         *
     3632         * @since 6.8.0
     3633         *
     3634         * @param array $blocks The block styles to process.
     3635         * @return array Sanitized block type styles.
     3636         */
     3637        protected static function remove_insecure_inner_block_styles( $blocks ) {
     3638                $sanitized = array();
     3639                foreach ( $blocks as $block_type => $block_input ) {
     3640                        $block_output = static::remove_insecure_styles( $block_input );
     3641
     3642                        if ( isset( $block_input['elements'] ) ) {
     3643                                $block_output['elements'] = static::remove_insecure_element_styles( $block_input['elements'] );
     3644                        }
     3645
     3646                        $sanitized[ $block_type ] = $block_output;
     3647                }
     3648                return $sanitized;
    36103649        }
    36113650
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r59418 r59802  
    47084708
    47094709        /**
     4710         * Test ensures that inner block type styles and their element styles are
     4711         * preserved for block style variations when removing insecure properties.
     4712         *
     4713         * @ticket 62372
     4714         */
     4715        public function test_block_style_variations_with_inner_blocks_and_elements() {
     4716                wp_set_current_user( static::$administrator_id );
     4717                register_block_style(
     4718                        array( 'core/group' ),
     4719                        array(
     4720                                'name'  => 'custom-group',
     4721                                'label' => 'Custom Group',
     4722                        )
     4723                );
     4724
     4725                $expected = array(
     4726                        'version' => WP_Theme_JSON::LATEST_SCHEMA,
     4727                        'styles'  => array(
     4728                                'blocks' => array(
     4729                                        'core/group' => array(
     4730                                                'color'      => array(
     4731                                                        'background' => 'blue',
     4732                                                ),
     4733                                                'variations' => array(
     4734                                                        'custom-group' => array(
     4735                                                                'color'    => array(
     4736                                                                        'background' => 'purple',
     4737                                                                ),
     4738                                                                'blocks'   => array(
     4739                                                                        'core/paragraph' => array(
     4740                                                                                'color'    => array(
     4741                                                                                        'text' => 'red',
     4742                                                                                ),
     4743                                                                                'elements' => array(
     4744                                                                                        'link' => array(
     4745                                                                                                'color'  => array(
     4746                                                                                                        'text' => 'blue',
     4747                                                                                                ),
     4748                                                                                                ':hover' => array(
     4749                                                                                                        'color' => array(
     4750                                                                                                                'text' => 'green',
     4751                                                                                                        ),
     4752                                                                                                ),
     4753                                                                                        ),
     4754                                                                                ),
     4755                                                                        ),
     4756                                                                        'core/heading'   => array(
     4757                                                                                'typography' => array(
     4758                                                                                        'fontSize' => '24px',
     4759                                                                                ),
     4760                                                                        ),
     4761                                                                ),
     4762                                                                'elements' => array(
     4763                                                                        'link' => array(
     4764                                                                                'color'  => array(
     4765                                                                                        'text' => 'yellow',
     4766                                                                                ),
     4767                                                                                ':hover' => array(
     4768                                                                                        'color' => array(
     4769                                                                                                'text' => 'orange',
     4770                                                                                        ),
     4771                                                                                ),
     4772                                                                        ),
     4773                                                                ),
     4774                                                        ),
     4775                                                ),
     4776                                        ),
     4777                                ),
     4778                        ),
     4779                );
     4780
     4781                $actual = WP_Theme_JSON::remove_insecure_properties( $expected );
     4782
     4783                // The sanitization processes blocks in a specific order which might differ to the theme.json input.
     4784                $this->assertEqualsCanonicalizing(
     4785                        $expected,
     4786                        $actual,
     4787                        'Block style variations data does not match when inner blocks or element styles present'
     4788                );
     4789        }
     4790
     4791        /**
     4792         * Test ensures that inner block type styles and their element styles for block
     4793         * style variations have all unsafe values removed.
     4794         *
     4795         * @ticket 62372
     4796         */
     4797        public function test_block_style_variations_with_invalid_inner_block_or_element_styles() {
     4798                wp_set_current_user( static::$administrator_id );
     4799                register_block_style(
     4800                        array( 'core/group' ),
     4801                        array(
     4802                                'name'  => 'custom-group',
     4803                                'label' => 'Custom Group',
     4804                        )
     4805                );
     4806
     4807                $input = array(
     4808                        'version' => WP_Theme_JSON::LATEST_SCHEMA,
     4809                        'styles'  => array(
     4810                                'blocks' => array(
     4811                                        'core/group' => array(
     4812                                                'variations' => array(
     4813                                                        'custom-group' => array(
     4814                                                                'blocks'   => array(
     4815                                                                        'core/paragraph' => array(
     4816                                                                                'color'      => array(
     4817                                                                                        'text' => 'red',
     4818                                                                                ),
     4819                                                                                'typography' => array(
     4820                                                                                        'fontSize' => 'alert(1)', // Should be removed.
     4821                                                                                ),
     4822                                                                                'elements'   => array(
     4823                                                                                        'link' => array(
     4824                                                                                                'color' => array(
     4825                                                                                                        'text' => 'blue',
     4826                                                                                                ),
     4827                                                                                                'css'   => 'unsafe-value', // Should be removed.
     4828                                                                                        ),
     4829                                                                                ),
     4830                                                                                'custom'     => 'unsafe-value', // Should be removed.
     4831                                                                        ),
     4832                                                                ),
     4833                                                                'elements' => array(
     4834                                                                        'link' => array(
     4835                                                                                'color'      => array(
     4836                                                                                        'text' => 'yellow',
     4837                                                                                ),
     4838                                                                                'javascript' => 'alert(1)', // Should be removed.
     4839                                                                        ),
     4840                                                                ),
     4841                                                        ),
     4842                                                ),
     4843                                        ),
     4844                                ),
     4845                        ),
     4846                );
     4847
     4848                $expected = array(
     4849                        'version' => WP_Theme_JSON::LATEST_SCHEMA,
     4850                        'styles'  => array(
     4851                                'blocks' => array(
     4852                                        'core/group' => array(
     4853                                                'variations' => array(
     4854                                                        'custom-group' => array(
     4855                                                                'blocks'   => array(
     4856                                                                        'core/paragraph' => array(
     4857                                                                                'color'    => array(
     4858                                                                                        'text' => 'red',
     4859                                                                                ),
     4860                                                                                'elements' => array(
     4861                                                                                        'link' => array(
     4862                                                                                                'color' => array(
     4863                                                                                                        'text' => 'blue',
     4864                                                                                                ),
     4865                                                                                        ),
     4866                                                                                ),
     4867                                                                        ),
     4868                                                                ),
     4869                                                                'elements' => array(
     4870                                                                        'link' => array(
     4871                                                                                'color' => array(
     4872                                                                                        'text' => 'yellow',
     4873                                                                                ),
     4874                                                                        ),
     4875                                                                ),
     4876                                                        ),
     4877                                                ),
     4878                                        ),
     4879                                ),
     4880                        ),
     4881                );
     4882
     4883                $actual = WP_Theme_JSON::remove_insecure_properties( $input );
     4884
     4885                // The sanitization processes blocks in a specific order which might differ to the theme.json input.
     4886                $this->assertEqualsCanonicalizing(
     4887                        $expected,
     4888                        $actual,
     4889                        'Insecure properties were not removed from block style variation inner block types or elements'
     4890                );
     4891        }
     4892
     4893        /**
    47104894         * Tests generating the spacing presets array based on the spacing scale provided.
    47114895         *
Note: See TracChangeset for help on using the changeset viewer.