Make WordPress Core

Changeset 59802


Ignore:
Timestamp:
02/10/2025 10:27:49 PM (6 weeks 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.