Skip to content

Commit 921d09c

Browse files
Media: Exclude IMG tags from crossorigin injection in media templates.
The client-side media processing feature added `crossorigin="anonymous"` to AUDIO, IMG, and VIDEO tags in the Backbone media templates printed by `wp_print_media_templates()`. Forcing the attribute on IMG tags triggers CORS requests that fail for images served without `Access-Control-Allow-Origin` headers, breaking media library previews for media offloaded to a CDN. This is the same problem previously fixed for `wp_add_crossorigin_attributes()` in [62048]: under `Document-Isolation-Policy: isolate-and-credentialless`, browsers load cross-origin images in credentialless mode, so the attribute is unnecessary on IMG tags. The media templates have a separate injection path that was missed at the time. Remove IMG from the list of tags receiving the attribute so both paths match. AUDIO and VIDEO tags are unchanged. Follow-up to [62048]. Props khokansardar, iamchitti, ianmjones, swissspidy. Fixes #65673. git-svn-id: https://develop.svn.wordpress.org/trunk@62819 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 2c49c06 commit 921d09c

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

src/wp-includes/media-template.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1619,11 +1619,17 @@ function wp_print_media_templates() {
16191619
* The crossorigin attribute is added unconditionally to all relevant
16201620
* media tags to ensure cross-origin isolation works regardless of
16211621
* the final URL value at render time.
1622+
*
1623+
* IMG is intentionally excluded, matching wp_add_crossorigin_attributes().
1624+
* Under Document-Isolation-Policy: isolate-and-credentialless the browser
1625+
* loads cross-origin images in credentialless mode without CORS headers,
1626+
* so adding crossorigin="anonymous" would force a CORS request and break
1627+
* previews of images served without Access-Control-Allow-Origin headers.
16221628
*/
16231629
$template_processor = new WP_HTML_Tag_Processor( $script_processor->get_modifiable_text() );
16241630
while ( $template_processor->next_tag() ) {
16251631
if (
1626-
in_array( $template_processor->get_tag(), array( 'AUDIO', 'IMG', 'VIDEO' ), true )
1632+
in_array( $template_processor->get_tag(), array( 'AUDIO', 'VIDEO' ), true )
16271633
&& ! is_string( $template_processor->get_attribute( 'crossorigin' ) )
16281634
) {
16291635
$template_processor->set_attribute( 'crossorigin', 'anonymous' );

tests/phpunit/tests/media/wpCrossOriginIsolation.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,4 +538,30 @@ public function test_output_buffer_handles_mixed_tags() {
538538
// Script and audio should have crossorigin.
539539
$this->assertSame( 2, substr_count( $output, 'crossorigin="anonymous"' ), 'Script and audio should both get crossorigin, but not img.' );
540540
}
541+
542+
/**
543+
* IMG tags in the media manager templates must not receive
544+
* crossorigin="anonymous", matching wp_add_crossorigin_attributes().
545+
*
546+
* Adding the attribute forces a CORS request that breaks previews of
547+
* images served without Access-Control-Allow-Origin headers, such as
548+
* media offloaded to a CDN.
549+
*
550+
* @ticket 65673
551+
*
552+
* @covers ::wp_print_media_templates
553+
*/
554+
public function test_print_media_templates_does_not_add_crossorigin_to_img() {
555+
require_once ABSPATH . WPINC . '/media-template.php';
556+
557+
add_filter( 'wp_client_side_media_processing_enabled', '__return_true' );
558+
559+
ob_start();
560+
wp_print_media_templates();
561+
$output = ob_get_clean();
562+
563+
$this->assertMatchesRegularExpression( '/<img\b/i', $output, 'Expected the media templates to contain IMG tags.' );
564+
$this->assertDoesNotMatchRegularExpression( '/<img\b[^>]*\bcrossorigin\b/i', $output, 'IMG tags in the media templates must not receive a crossorigin attribute.' );
565+
$this->assertMatchesRegularExpression( '/<(?:audio|video)\b[^>]*crossorigin="anonymous"/i', $output, 'AUDIO and VIDEO tags in the media templates should still receive crossorigin="anonymous".' );
566+
}
541567
}

0 commit comments

Comments
 (0)