Make WordPress Core

Changeset 61947


Ignore:
Timestamp:
03/11/2026 11:38:35 PM (6 months ago)
Author:
adamsilverstein
Message:

Editor: Skip cross-origin isolation for third-party page builders.

Document-Isolation-Policy (DIP) isolates the document and blocks same-origin iframe access that page builders rely on. Skip DIP setup when a third-party page builder overrides the block editor via a custom action query parameter.

Also gates wp_is_client_side_media_processing_enabled() on a secure context check, since SharedArrayBuffer requires a secure context (HTTPS or localhost).

Props adamsilverstein, westonruter, mukesh27, louiswol94, manhar, illuminea.
Fixes #64803.

Location:
trunk
Files:
4 edited

Legend:

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

    r61934 r61947  
    64126412 */
    64136413function wp_is_client_side_media_processing_enabled(): bool {
     6414        // This is due to SharedArrayBuffer requiring a secure context.
     6415        $host    = strtolower( (string) strtok( $_SERVER['HTTP_HOST'] ?? '', ':' ) );
     6416        $enabled = ( is_ssl() || 'localhost' === $host || str_ends_with( $host, '.localhost' ) );
     6417
    64146418        /**
    64156419         * Filters whether client-side media processing is enabled.
     
    64176421         * @since 7.0.0
    64186422         *
    6419          * @param bool $enabled Whether client-side media processing is enabled. Default true.
    6420          */
    6421         return (bool) apply_filters( 'wp_client_side_media_processing_enabled', true );
     6423         * @param bool $enabled Whether client-side media processing is enabled. Default true if the page is served in a secure context.
     6424         */
     6425        return (bool) apply_filters( 'wp_client_side_media_processing_enabled', $enabled );
    64226426}
    64236427
     
    64326436        }
    64336437
    6434         wp_add_inline_script( 'wp-block-editor', 'window.__clientSideMediaProcessing = true', 'before' );
     6438        wp_add_inline_script( 'wp-block-editor', 'window.__clientSideMediaProcessing = true;', 'before' );
    64356439
    64366440        $chromium_version = wp_get_chromium_major_version();
     
    64786482 * on supported browsers (Chromium 137+).
    64796483 *
     6484 * Skips setup when a third-party page builder overrides the block
     6485 * editor via a custom `action` query parameter, as DIP would block
     6486 * same-origin iframe access that these editors rely on.
     6487 *
    64806488 * @since 7.0.0
    64816489 */
     
    64926500
    64936501        if ( ! $screen->is_block_editor() && 'site-editor' !== $screen->id && ! ( 'widgets' === $screen->id && wp_use_widgets_block_editor() ) ) {
     6502                return;
     6503        }
     6504
     6505        /*
     6506         * Skip when a third-party page builder overrides the block editor.
     6507         * DIP isolates the document into its own agent cluster,
     6508         * which blocks same-origin iframe access that these editors rely on.
     6509         */
     6510        if ( isset( $_GET['action'] ) && 'edit' !== $_GET['action'] ) {
    64946511                return;
    64956512        }
  • trunk/tests/phpunit/tests/media/wpCrossOriginIsolation.php

    r61844 r61947  
    77 * @covers ::wp_set_up_cross_origin_isolation
    88 * @covers ::wp_start_cross_origin_isolation_output_buffer
     9 * @covers ::wp_is_client_side_media_processing_enabled
    910 */
    1011class Tests_Media_wpCrossOriginIsolation extends WP_UnitTestCase {
     
    1213        /**
    1314         * Original HTTP_USER_AGENT value.
    14          *
    15          * @var string|null
    16          */
    17         private $original_user_agent;
     15         */
     16        private ?string $original_user_agent;
     17
     18        /**
     19         * Original HTTP_HOST value.
     20         */
     21        private ?string $original_http_host;
     22
     23        /**
     24         * Original HTTPS value.
     25         */
     26        private ?string $original_https;
     27
     28        /**
     29         * Original $_GET['action'] value.
     30         */
     31        private ?string $original_get_action;
    1832
    1933        public function set_up() {
    2034                parent::set_up();
    21                 $this->original_user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null;
     35                $this->original_user_agent = $_SERVER['HTTP_USER_AGENT'] ?? null;
     36                $this->original_http_host  = $_SERVER['HTTP_HOST'] ?? null;
     37                $this->original_https      = $_SERVER['HTTPS'] ?? null;
     38                $this->original_get_action = $_GET['action'] ?? null;
    2239        }
    2340
     
    2946                }
    3047
     48                if ( null === $this->original_http_host ) {
     49                        unset( $_SERVER['HTTP_HOST'] );
     50                } else {
     51                        $_SERVER['HTTP_HOST'] = $this->original_http_host;
     52                }
     53
     54                if ( null === $this->original_https ) {
     55                        unset( $_SERVER['HTTPS'] );
     56                } else {
     57                        $_SERVER['HTTPS'] = $this->original_https;
     58                }
     59
     60                if ( null === $this->original_get_action ) {
     61                        unset( $_GET['action'] );
     62                } else {
     63                        $_GET['action'] = $this->original_get_action;
     64                }
     65
    3166                // Clean up any output buffers started during tests.
    3267                while ( ob_get_level() > 1 ) {
     
    126161
    127162        /**
     163         * @ticket 64803
     164         */
     165        public function test_client_side_processing_disabled_on_non_secure_origin() {
     166                $_SERVER['HTTP_HOST'] = 'example.com';
     167                $_SERVER['HTTPS']     = '';
     168
     169                $this->assertFalse(
     170                        wp_is_client_side_media_processing_enabled(),
     171                        'Client-side media processing should be disabled on non-secure, non-localhost origins.'
     172                );
     173        }
     174
     175        /**
     176         * @ticket 64803
     177         */
     178        public function test_client_side_processing_enabled_on_localhost() {
     179                $_SERVER['HTTP_HOST'] = 'localhost';
     180                $_SERVER['HTTPS']     = '';
     181
     182                $this->assertTrue(
     183                        wp_is_client_side_media_processing_enabled(),
     184                        'Client-side media processing should be enabled on localhost.'
     185                );
     186        }
     187
     188        /**
    128189         * This test must run in a separate process because the output buffer
    129190         * callback sends HTTP headers via header(), which would fail in the
  • trunk/tests/phpunit/tests/rest-api/rest-attachments-controller.php

    r61809 r61947  
    31633163         */
    31643164        public function test_sideload_scaled_image() {
     3165                add_filter( 'wp_client_side_media_processing_enabled', '__return_true' );
     3166                // Reinitialize REST server so the sideload route is registered.
     3167                global $wp_rest_server;
     3168                $wp_rest_server = new Spy_REST_Server();
     3169                do_action( 'rest_api_init', $wp_rest_server );
     3170
    31653171                wp_set_current_user( self::$author_id );
    31663172
     
    32163222         */
    32173223        public function test_sideload_scaled_image_requires_auth() {
     3224                add_filter( 'wp_client_side_media_processing_enabled', '__return_true' );
     3225                // Reinitialize REST server so the sideload route is registered.
     3226                global $wp_rest_server;
     3227                $wp_rest_server = new Spy_REST_Server();
     3228                do_action( 'rest_api_init', $wp_rest_server );
     3229
    32183230                wp_set_current_user( self::$author_id );
    32193231
     
    32453257         */
    32463258        public function test_sideload_route_includes_scaled_enum() {
     3259                add_filter( 'wp_client_side_media_processing_enabled', '__return_true' );
     3260                // Reinitialize REST server so the sideload route is registered.
     3261                global $wp_rest_server;
     3262                $wp_rest_server = new Spy_REST_Server();
     3263                do_action( 'rest_api_init', $wp_rest_server );
     3264
    32473265                $server = rest_get_server();
    32483266                $routes = $server->get_routes();
     
    32673285         */
    32683286        public function test_sideload_scaled_unique_filename() {
     3287                add_filter( 'wp_client_side_media_processing_enabled', '__return_true' );
     3288                // Reinitialize REST server so the sideload route is registered.
     3289                global $wp_rest_server;
     3290                $wp_rest_server = new Spy_REST_Server();
     3291                do_action( 'rest_api_init', $wp_rest_server );
     3292
    32693293                wp_set_current_user( self::$author_id );
    32703294
     
    33013325         */
    33023326        public function test_sideload_scaled_unique_filename_conflict() {
     3327                add_filter( 'wp_client_side_media_processing_enabled', '__return_true' );
     3328                // Reinitialize REST server so the sideload route is registered.
     3329                global $wp_rest_server;
     3330                $wp_rest_server = new Spy_REST_Server();
     3331                do_action( 'rest_api_init', $wp_rest_server );
     3332
    33033333                wp_set_current_user( self::$author_id );
    33043334
  • trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php

    r61703 r61947  
    1616        public function set_up() {
    1717                parent::set_up();
     18
     19                // Ensure client-side media processing is enabled so the sideload route is registered.
     20                add_filter( 'wp_client_side_media_processing_enabled', '__return_true' );
    1821
    1922                /** @var WP_REST_Server $wp_rest_server */
Note: See TracChangeset for help on using the changeset viewer.