diff --git a/src/wp-includes/media-template.php b/src/wp-includes/media-template.php
index 20f485b5416e5..460cf3b3020e5 100644
--- a/src/wp-includes/media-template.php
+++ b/src/wp-includes/media-template.php
@@ -1619,11 +1619,17 @@ function wp_print_media_templates() {
* The crossorigin attribute is added unconditionally to all relevant
* media tags to ensure cross-origin isolation works regardless of
* the final URL value at render time.
+ *
+ * IMG is intentionally excluded, matching wp_add_crossorigin_attributes().
+ * Under Document-Isolation-Policy: isolate-and-credentialless the browser
+ * loads cross-origin images in credentialless mode without CORS headers,
+ * so adding crossorigin="anonymous" would force a CORS request and break
+ * previews of images served without Access-Control-Allow-Origin headers.
*/
$template_processor = new WP_HTML_Tag_Processor( $script_processor->get_modifiable_text() );
while ( $template_processor->next_tag() ) {
if (
- in_array( $template_processor->get_tag(), array( 'AUDIO', 'IMG', 'VIDEO' ), true )
+ in_array( $template_processor->get_tag(), array( 'AUDIO', 'VIDEO' ), true )
&& ! is_string( $template_processor->get_attribute( 'crossorigin' ) )
) {
$template_processor->set_attribute( 'crossorigin', 'anonymous' );
diff --git a/tests/phpunit/tests/media/wpCrossOriginIsolation.php b/tests/phpunit/tests/media/wpCrossOriginIsolation.php
index 1275ed21c3bc8..b1c40e8596780 100644
--- a/tests/phpunit/tests/media/wpCrossOriginIsolation.php
+++ b/tests/phpunit/tests/media/wpCrossOriginIsolation.php
@@ -538,4 +538,30 @@ public function test_output_buffer_handles_mixed_tags() {
// Script and audio should have crossorigin.
$this->assertSame( 2, substr_count( $output, 'crossorigin="anonymous"' ), 'Script and audio should both get crossorigin, but not img.' );
}
+
+ /**
+ * IMG tags in the media manager templates must not receive
+ * crossorigin="anonymous", matching wp_add_crossorigin_attributes().
+ *
+ * Adding the attribute forces a CORS request that breaks previews of
+ * images served without Access-Control-Allow-Origin headers, such as
+ * media offloaded to a CDN.
+ *
+ * @ticket 65673
+ *
+ * @covers ::wp_print_media_templates
+ */
+ public function test_print_media_templates_does_not_add_crossorigin_to_img() {
+ require_once ABSPATH . WPINC . '/media-template.php';
+
+ add_filter( 'wp_client_side_media_processing_enabled', '__return_true' );
+
+ ob_start();
+ wp_print_media_templates();
+ $output = ob_get_clean();
+
+ $this->assertMatchesRegularExpression( '/
assertDoesNotMatchRegularExpression( '/
]*\bcrossorigin\b/i', $output, 'IMG tags in the media templates must not receive a crossorigin attribute.' );
+ $this->assertMatchesRegularExpression( '/<(?:audio|video)\b[^>]*crossorigin="anonymous"/i', $output, 'AUDIO and VIDEO tags in the media templates should still receive crossorigin="anonymous".' );
+ }
}