Make WordPress Core

Changeset 60648


Ignore:
Timestamp:
08/19/2025 06:50:05 PM (12 months ago)
Author:
jonsurrell
Message:

Editor: Ensure preloading middleware JSON is correctly encoded.

Adds the appropriate JSON flags to wp_json_encode() to safely encode data for use in script tags.

Developed in https://github.com/WordPress/wordpress-develop/pull/8145.

Props jonsurrell, bernhard-reiter, dmsnell, artpi, ankitkumarshah, abcd95, dilipbheda, sainathpoojary, shanemuir.
Fixes #62797.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-editor.php

    r60003 r60648  
    767767                sprintf(
    768768                        'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );',
    769                         wp_json_encode( $preload_data )
     769                        wp_json_encode( $preload_data, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
    770770                ),
    771771                'after'
  • trunk/tests/phpunit/tests/blocks/editor.php

    r59775 r60648  
    1010 */
    1111class Tests_Blocks_Editor extends WP_UnitTestCase {
    12 
    1312        /**
    1413         * Sets up each test method.
     
    632631                $after = implode( '', wp_scripts()->registered['wp-api-fetch']->extra['after'] );
    633632                $this->assertStringContainsString( 'wp.apiFetch.createPreloadingMiddleware', $after );
    634                 $this->assertStringContainsString( '"\/wp\/v2\/blocks"', $after );
    635                 $this->assertStringContainsString( '"\/wp\/v2\/types"', $after );
     633                $this->assertStringContainsString( '"/wp/v2/blocks"', $after );
     634                $this->assertStringContainsString( '"/wp/v2/types"', $after );
    636635        }
    637636
     
    698697                        'a string without a slash'               => array(
    699698                                'preload_paths' => array( 'wp/v2/blocks' ),
    700                                 'expected'      => '\/wp\/v2\/blocks',
     699                                'expected'      => '/wp/v2/blocks',
    701700                        ),
    702701                        'a string with a slash'                  => array(
    703702                                'preload_paths' => array( '/wp/v2/blocks' ),
    704                                 'expected'      => '\/wp\/v2\/blocks',
     703                                'expected'      => '/wp/v2/blocks',
    705704                        ),
    706705                        'a string starting with a question mark' => array(
     
    710709                        'an array with a string without a slash' => array(
    711710                                'preload_paths' => array( array( 'wp/v2/blocks', 'OPTIONS' ) ),
    712                                 'expected'      => '\/wp\/v2\/blocks',
     711                                'expected'      => '/wp/v2/blocks',
    713712                        ),
    714713                        'an array with a string with a slash'    => array(
    715714                                'preload_paths' => array( array( '/wp/v2/blocks', 'OPTIONS' ) ),
    716                                 'expected'      => '\/wp\/v2\/blocks',
     715                                'expected'      => '/wp/v2/blocks',
    717716                        ),
    718717                        'an array with a string starting with a question mark' => array(
    719718                                'preload_paths' => array( array( '?context=edit', 'OPTIONS' ) ),
    720                                 'expected'      => '\/?context=edit',
    721                         ),
    722                 );
     719                                'expected'      => '/?context=edit',
     720                        ),
     721                );
     722        }
     723
     724        /**
     725         * @ticket 62797
     726         *
     727         * @covers ::block_editor_rest_api_preload
     728         *
     729         * Some valid JSON-encoded data is dangerous to embed in HTML without appropriate
     730         * escaping. This test includes an example of data that would prevent the enclosing
     731         * `<script></script>` tag from closing on its apparent closer and remain open.
     732         */
     733        public function test_ensure_preload_data_script_tag_closes() {
     734                add_theme_support( 'html5', array( 'script' ) );
     735                register_rest_route(
     736                        'test/v0',
     737                        'test-62797',
     738                        array(
     739                                'methods'             => 'GET',
     740                                'callback'            => function () {
     741                                        return 'Unclosed comment and a script open tag <!--<script>';
     742                                },
     743                                'permission_callback' => '__return_true',
     744                        )
     745                );
     746
     747                // Prevent a bunch of noisy or unstable data from being included in the test output.
     748                wp_scripts()->registered['wp-api-fetch']->ver            = 'test';
     749                wp_scripts()->registered['wp-api-fetch']->extra['after'] = array();
     750
     751                block_editor_rest_api_preload(
     752                        array( '/test/v0/test-62797' ),
     753                        new WP_Block_Editor_Context()
     754                );
     755
     756                ob_start();
     757                wp_scripts()->do_item( 'wp-api-fetch' );
     758                $output = ob_get_clean();
     759
     760                $baseurl  = site_url();
     761                $expected = <<<HTML
     762<script src="{$baseurl}/wp-includes/js/dist/api-fetch.min.js?ver=test" id="wp-api-fetch-js"></script>
     763<script id="wp-api-fetch-js-after">
     764wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( {"/test/v0/test-62797":{"body":["Unclosed comment and a script open tag \\u003C!--\\u003Cscript\\u003E"],"headers":{"Allow":"GET"}}} ) );
     765</script>
     766
     767HTML;
     768                $this->assertEqualHTML( $expected, $output );
    723769        }
    724770}
Note: See TracChangeset for help on using the changeset viewer.