Make WordPress Core

Changeset 55345


Ignore:
Timestamp:
02/15/2023 03:55:12 AM (15 months ago)
Author:
peterwilsoncc
Message:

Editor: Prevent KSES stripping global layout style properties.

Layout style properties are stored using indirect values, rather than direct CSS properties.

Allow users without the unfiltered_html capability to modify global styles using the indirect block spacing properties contentSize, wideSize, and blockGap, using a mapping of the eventual CSS property to the indirect property stored in theme.json. The mapped CSS property is then used for CSS validation.

Props andrewserong, costdev, hellofromtonya, mamaduka, mmtr86.
Fixes #57321.

Location:
trunk
Files:
2 edited

Legend:

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

    r55285 r55345  
    264264
    265265    /**
     266     * Indirect metadata for style properties that are not directly output.
     267     *
     268     * Each element maps from a CSS property name to an array of
     269     * paths to the value in theme.json & block attributes.
     270     *
     271     * Indirect properties are not output directly by `compute_style_properties`,
     272     * but are used elsewhere in the processing of global styles. The indirect
     273     * property is used to validate whether or not a style value is allowed.
     274     *
     275     * @since 6.1.2
     276     * @var array
     277     */
     278    const INDIRECT_PROPERTIES_METADATA = array(
     279        'gap'        => array(
     280            array( 'spacing', 'blockGap' ),
     281        ),
     282        'column-gap' => array(
     283            array( 'spacing', 'blockGap', 'left' ),
     284        ),
     285        'row-gap'    => array(
     286            array( 'spacing', 'blockGap', 'top' ),
     287        ),
     288        'max-width'  => array(
     289            array( 'layout', 'contentSize' ),
     290            array( 'layout', 'wideSize' ),
     291        ),
     292    );
     293
     294    /**
    266295     * Protected style properties.
    267296     *
     
    29502979            }
    29512980        }
     2981
     2982        // Ensure indirect properties not included in any `PRESETS_METADATA` value are allowed.
     2983        static::remove_indirect_properties( $input, $output );
     2984
    29522985        return $output;
    29532986    }
     
    29783011            }
    29793012        }
     3013
     3014        // Ensure indirect properties not handled by `compute_style_properties` are allowed.
     3015        static::remove_indirect_properties( $input, $output );
     3016
    29803017        return $output;
    29813018    }
     
    29943031        $filtered          = esc_html( safecss_filter_attr( $style_to_validate ) );
    29953032        return ! empty( trim( $filtered ) );
     3033    }
     3034
     3035    /**
     3036     * Removes indirect properties from the given input node and
     3037     * sets in the given output node.
     3038     *
     3039     * @since 6.1.2
     3040     *
     3041     * @param array $input  Node to process.
     3042     * @param array $output The processed node. Passed by reference.
     3043     */
     3044    private static function remove_indirect_properties( $input, &$output ) {
     3045        foreach ( static::INDIRECT_PROPERTIES_METADATA as $property => $paths ) {
     3046            foreach ( $paths as $path ) {
     3047                $value = _wp_array_get( $input, $path );
     3048                if (
     3049                    is_string( $value ) &&
     3050                    static::is_safe_css_declaration( $property, $value )
     3051                ) {
     3052                    _wp_array_set( $output, $path, $value );
     3053                }
     3054            }
     3055        }
    29963056    }
    29973057
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r55285 r55345  
    24282428
    24292429    /**
     2430     * @ticket 57321
     2431     *
     2432     * @covers WP_Theme_JSON::remove_insecure_properties
     2433     */
     2434    public function test_remove_insecure_properties_should_allow_indirect_properties() {
     2435        $actual = WP_Theme_JSON::remove_insecure_properties(
     2436            array(
     2437                'version'  => WP_Theme_JSON::LATEST_SCHEMA,
     2438                'styles'   => array(
     2439                    'spacing' => array(
     2440                        'blockGap' => '3em',
     2441                    ),
     2442                    'blocks'  => array(
     2443                        'core/social-links' => array(
     2444                            'spacing' => array(
     2445                                'blockGap' => array(
     2446                                    'left' => '2em',
     2447                                    'top'  => '1em',
     2448                                ),
     2449                            ),
     2450                        ),
     2451                    ),
     2452                ),
     2453                'settings' => array(
     2454                    'layout' => array(
     2455                        'contentSize' => '800px',
     2456                        'wideSize'    => '1000px',
     2457                    ),
     2458                ),
     2459            )
     2460        );
     2461
     2462        $expected = array(
     2463            'version'  => WP_Theme_JSON::LATEST_SCHEMA,
     2464            'styles'   => array(
     2465                'spacing' => array(
     2466                    'blockGap' => '3em',
     2467                ),
     2468                'blocks'  => array(
     2469                    'core/social-links' => array(
     2470                        'spacing' => array(
     2471                            'blockGap' => array(
     2472                                'left' => '2em',
     2473                                'top'  => '1em',
     2474                            ),
     2475                        ),
     2476                    ),
     2477                ),
     2478            ),
     2479            'settings' => array(
     2480                'layout' => array(
     2481                    'contentSize' => '800px',
     2482                    'wideSize'    => '1000px',
     2483                ),
     2484            ),
     2485        );
     2486
     2487        $this->assertSameSetsWithIndex( $expected, $actual );
     2488    }
     2489
     2490    /**
    24302491     * @ticket 56467
    24312492     */
Note: See TracChangeset for help on using the changeset viewer.