Skip to content

Media: Stop forcing crossorigin on IMG tags in media templates - #80532

Merged
adamsilverstein merged 4 commits into
trunkfrom
fix/media-templates-img-crossorigin
Jul 23, 2026
Merged

Media: Stop forcing crossorigin on IMG tags in media templates#80532
adamsilverstein merged 4 commits into
trunkfrom
fix/media-templates-img-crossorigin

Conversation

@adamsilverstein

@adamsilverstein adamsilverstein commented Jul 21, 2026

Copy link
Copy Markdown
Member

What?

Fixes #80535

Stops forcing crossorigin="anonymous" onto img tags in the media manager templates.

Companion to the Core fix for Trac #65673 (wordpress-develop#12615, wordpress-develop#12616).

Why?

Under Document-Isolation-Policy: isolate-and-credentialless the browser already loads cross-origin images in credentialless mode. Forcing crossorigin="anonymous" triggers a CORS request that fails for images served without Access-Control-Allow-Origin headers, so media library previews break for offloaded/CDN media.

#76618 removed img from gutenberg_add_crossorigin_attributes() and the editor content hook for exactly this reason, but missed the third injection path: gutenberg_override_media_templates() still str_replaces crossorigin="anonymous" onto every <img, <audio, and <video in the Backbone media templates. That stale img entry was carried into Core by the client-side media processing backport, producing the regression reported in Trac #65673.

The plain str_replace also produces duplicate attributes on WordPress 7.1, where Core's wp_print_media_templates() now injects crossorigin itself (<img crossorigin="anonymous" crossorigin="anonymous" …> — visible in the phpunit output before this fix).

How?

Reworks the override to mirror Core's Tag Processor approach:

  • Extracts each <script type="text/html"> template's content and processes it with WP_HTML_Tag_Processor (template text is raw text to the processor, matching Core's implementation in wp_print_media_templates()).
  • Adds crossorigin="anonymous" only to AUDIO and VIDEO tags that don't already have it — no duplicates on WP 7.1, still effective on older WordPress versions.
  • Leaves IMG tags untouched. (An earlier revision also stripped the attribute where Core had added it, but no released WordPress version does that — only 7.1 Beta 1/2 did, and the Core fix (r62819) shipped in 7.1 Beta 3 — so the extra code wasn't worth carrying.)

The processing logic is extracted into gutenberg_update_media_template_crossorigin_attributes() so it can be unit tested directly.

Testing Instructions

Test in Playground

  1. Run a site whose media is served from a host without CORS headers (e.g. install a mu-plugin that filters wp_prepare_attachment_for_js to rewrite url/sizes[*].url to an external host, per this gist), on Chrome ≥ 137 over HTTPS or localhost so DIP is active.
  2. Open the post editor → Image block → Media Library.
  3. Without this PR: grid thumbnails carry crossorigin="anonymous" and previews fail with CORS errors in the console. With this PR: no crossorigin on img tags, previews load.
  4. npm run test:unit:php:base -- --filter media_template passes.

Automated tests

  • test_gutenberg_override_media_templates asserts audio/video get crossorigin and no duplicates are produced.
  • New test_gutenberg_update_media_template_crossorigin_attributes covers the add/skip branches and IMG exclusion directly, including non-template <script> content being left untouched.

The media templates override added crossorigin="anonymous" to every
img tag via str_replace. Under Document-Isolation-Policy:
isolate-and-credentialless the browser already loads cross-origin
images in credentialless mode, so forcing the attribute triggers a
CORS request that breaks previews of images served without CORS
headers, such as media offloaded to a CDN.

Rework the override to use the HTML Tag Processor: add the attribute
only to AUDIO and VIDEO tags that lack it, and strip it from IMG tags
where WordPress Core has already added it (7.1 betas), so the plugin
also repairs previews on affected Core versions. This mirrors the fix
Core applied to wp_add_crossorigin_attributes() in r62048 and avoids
the duplicate attributes previously produced on WordPress 7.1.

See https://core.trac.wordpress.org/ticket/65673
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Flaky tests detected in 22bb88c.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/29850100249
📝 Reported issues:

@adamsilverstein adamsilverstein added [Type] Bug An existing feature does not function as intended [Feature] Media Anything that impacts the experience of managing media Backport to WP 7.1 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta labels Jul 21, 2026
@adamsilverstein adamsilverstein self-assigned this Jul 21, 2026
@adamsilverstein
adamsilverstein removed the request for review from spacedmonkey July 21, 2026 19:44
@adamsilverstein adamsilverstein added [Feature] Client Side Media Media processing in the browser with WASM and removed [Feature] Media Anything that impacts the experience of managing media labels Jul 21, 2026
@github-project-automation github-project-automation Bot moved this to 🔎 Needs Review in WordPress 7.1 Editor Tasks Jul 21, 2026
@adamsilverstein adamsilverstein added the [Status] In Progress Tracking issues with work in progress label Jul 21, 2026

@andrewserong andrewserong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic looks consistent with core except for one bit (the removal of crossorigin on img) but that looks intentional.

Code-wise this looks good — I'm going a little faster with reviews today than I'd usually like so I haven't actually tested this PR properly. Just wanted to give a tentative approval in case you're trying to get this in quickly. Happy to take a more detailed look later in the week if you need it, though!

Comment thread lib/media/load.php Outdated
Comment on lines +506 to +511
} elseif (
'IMG' === $tag
&& null !== $template_processor->get_attribute( 'crossorigin' )
) {
$template_processor->remove_attribute( 'crossorigin' );
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double-checking: is this to support removing crossorigin that has been added in WP core versions < 7.1? If so that makes sense to me!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so, let me double check that its really needed.

@adamsilverstein adamsilverstein Jul 22, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question - I checked the core history to be sure. No released WordPress version ever adds crossorigin to IMG in the media templates. The injection only existed in pre-releases:

  • 7.0 Beta 1-5 carried it via the original client-side media backport, but it was removed in 7.0 Beta 6 (c863860) - 7.0 final has no crossorigin injection at all.
  • It came back with the reintroduction on trunk (51a5f4d), so 7.1 Beta 1 and Beta 2 (and nightlies since late May) do add it.
  • The core fix (r62819) landed in 7.1 Beta 3, which excludes IMG again.

So the removal here only matters for sites still on 7.1 Beta 1/2 (or older nightlies). I think we can just drop it, seems excessive.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up: since no released WordPress version ever ships the IMG injection and the Core fix landed in 7.1 Beta 3, the strip only served sites still on Beta 1/2 - not worth the extra code. Dropped it in e330019; the plugin now just leaves IMG tags untouched.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up: since no released WordPress version ever ships the IMG injection and the Core fix landed in 7.1 Beta 3, the strip only served sites still on Beta 1/2 - not worth the extra code. Dropped it in e330019; the plugin now just leaves IMG tags untouched.

Looks good 👍

No released WordPress version adds crossorigin to IMG in the media
templates, and the core fix (r62819) shipped in 7.1 Beta 3, so the
strip only served sites on 7.1 Beta 1/2. Not worth the extra code;
the plugin now simply leaves IMG tags untouched.
@adamsilverstein
adamsilverstein merged commit cb53341 into trunk Jul 23, 2026
49 of 52 checks passed
@github-project-automation github-project-automation Bot moved this from 🔎 Needs Review to ✅ Done in WordPress 7.1 Editor Tasks Jul 23, 2026
@adamsilverstein
adamsilverstein deleted the fix/media-templates-img-crossorigin branch July 23, 2026 02:24
@github-actions github-actions Bot added this to the Gutenberg 23.7 milestone Jul 23, 2026
@github-actions github-actions Bot removed the Backport to WP 7.1 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Jul 23, 2026
gutenbergplugin pushed a commit that referenced this pull request Jul 23, 2026
Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>
@github-actions github-actions Bot added the Backported to WP Core Pull request that has been successfully merged into WP Core label Jul 23, 2026
@github-actions

Copy link
Copy Markdown

I just cherry-picked this PR to the wp/7.1 branch to get it included in the next release: 1c5f420

@adamsilverstein adamsilverstein added the Backport to Gutenberg RC Pull request that needs to be backported to a Gutenberg release candidate (RC) label Jul 23, 2026
pento pushed a commit to WordPress/wordpress-develop that referenced this pull request Jul 29, 2026
This updates the pinned commit hash of the Gutenberg repository from `4997026b75c922d8a6f77a03d72ed7cad04c7073` to `fd715a6833679d098d9fee84b642f8f1bc27341b`.

A full list of changes included in this commit can be found on GitHub: 
WordPress/gutenberg@4997026...fd715a6

- Update view config API versioning (WordPress/gutenberg#80319)
- Perf Tests: Fix 'Selecting blocks' metric reporting 0 ms (WordPress/gutenberg#80524)
- Notes: Register the inline note format at import time (WordPress/gutenberg#80576)
- Media: Stop forcing crossorigin on IMG tags in media templates (WordPress/gutenberg#80532)
- GradientPicker: select by slug so two presets sharing a gradient keep their identity (WordPress/gutenberg#80554)
- Media Editor: Show a loading state while the cropped file loads (WordPress/gutenberg#80460)
- Remove default paragraph from tab-panel template (WordPress/gutenberg#80565)
- Global Styles: Resolve link element styles in block inspector controls for blocks that are links (WordPress/gutenberg#80607)
- Media REST API: Backport sideload from url path upload size check (WordPress/gutenberg#80659)
- Rich text: remove tabIndex from editable elements again to fix shift+click selection (WordPress/gutenberg#80651)
- Gallery: make dynamic mode conversion a single undo level (WordPress/gutenberg#80665)
- Background image control: Remove duplicated focus ring (WordPress/gutenberg#80671)
- Detach core's note mention kses filter in the baseline strip test (WordPress/gutenberg#80656)
- wp-build: sync the page template preload field list with core-data (WordPress/gutenberg#80648)
- Read the contentEditable attribute in ownsSelection, not isContentEditable (WordPress/gutenberg#80549)
- Writing flow: extend block selections with shift+arrow when there is no native selection (WordPress/gutenberg#80687)
- Notes: Capture the target block before saving a block-level note (WordPress/gutenberg#80690)
- Theme JSON: Level block-level preset class specificity with :where() (WordPress/gutenberg#80657)
- Notes: Sync the sidebar selection to the inline marker under the caret (WordPress/gutenberg#80610)
- Writing flow: use isMultiSelecting for shift+click (WordPress/gutenberg#80286) (WordPress/gutenberg#80726)
- Block supports: Return from layout support before resolving global settings (WordPress/gutenberg#80771)
- Notes: Report save success consistently from note actions (WordPress/gutenberg#80748)
- Dynamic Gallery: Rename toolbar button to Detach and add a modal explaining what will happen (WordPress/gutenberg#80727) (WordPress/gutenberg#80774)
- ToolsPanel: Migrate styles to an SCSS Module (WordPress/gutenberg#80445) (WordPress/gutenberg#80800)
- Add a responsiveEditingEnabled editor setting to hide the Responsive styles option (WordPress/gutenberg#80814)
- iOS: remove jumping hack, add typewriter (WordPress/gutenberg#74596)
- Writing flow: stop the page scrolling on caret moves within blocks taller than the viewport (WordPress/gutenberg#80708)
- Global Styles: Put the inheritance UI behind a Gutenberg experiment (… (WordPress/gutenberg#80818)
- Notes: Cancel in-flight hover highlight when focus leaves a note thread (WordPress/gutenberg#80752)
- Block Editor: Try to fix typing performance regression (WordPress/gutenberg#80507)
- List Block: Preserve ordered type on indent (WordPress/gutenberg#75353)
- Make editableRoot a private block setting Symbol, not a public support (WordPress/gutenberg#80820)
- Fix cursor position during forward delete of empty blocks (WordPress/gutenberg#80827)
- Navigation: Fixes `aria-expanded` not updating on hover submenu inside overlay (WordPress/gutenberg#80828)
- Remove redundant @jest-environment jsdom pragma and lint against it (WordPress/gutenberg#80676)
- View config: reject shape-mismatched merges, define empty-array semantics, strip nulls from appended members (WordPress/gutenberg#80829)
- Editor: leave undo to the browser in fields that handle their own undo (WordPress/gutenberg#80768)
- Fix: New route-based admin pages are empty when no JS (WordPress/gutenberg#80839)

Props wildworks.
See #65529.

git-svn-id: https://develop.svn.wordpress.org/trunk@62896 602fd350-edb4-49c9-b593-d223f7449a82
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Jul 29, 2026
This updates the pinned commit hash of the Gutenberg repository from `4997026b75c922d8a6f77a03d72ed7cad04c7073` to `fd715a6833679d098d9fee84b642f8f1bc27341b`.

A full list of changes included in this commit can be found on GitHub: 
WordPress/gutenberg@4997026...fd715a6

- Update view config API versioning (WordPress/gutenberg#80319)
- Perf Tests: Fix 'Selecting blocks' metric reporting 0 ms (WordPress/gutenberg#80524)
- Notes: Register the inline note format at import time (WordPress/gutenberg#80576)
- Media: Stop forcing crossorigin on IMG tags in media templates (WordPress/gutenberg#80532)
- GradientPicker: select by slug so two presets sharing a gradient keep their identity (WordPress/gutenberg#80554)
- Media Editor: Show a loading state while the cropped file loads (WordPress/gutenberg#80460)
- Remove default paragraph from tab-panel template (WordPress/gutenberg#80565)
- Global Styles: Resolve link element styles in block inspector controls for blocks that are links (WordPress/gutenberg#80607)
- Media REST API: Backport sideload from url path upload size check (WordPress/gutenberg#80659)
- Rich text: remove tabIndex from editable elements again to fix shift+click selection (WordPress/gutenberg#80651)
- Gallery: make dynamic mode conversion a single undo level (WordPress/gutenberg#80665)
- Background image control: Remove duplicated focus ring (WordPress/gutenberg#80671)
- Detach core's note mention kses filter in the baseline strip test (WordPress/gutenberg#80656)
- wp-build: sync the page template preload field list with core-data (WordPress/gutenberg#80648)
- Read the contentEditable attribute in ownsSelection, not isContentEditable (WordPress/gutenberg#80549)
- Writing flow: extend block selections with shift+arrow when there is no native selection (WordPress/gutenberg#80687)
- Notes: Capture the target block before saving a block-level note (WordPress/gutenberg#80690)
- Theme JSON: Level block-level preset class specificity with :where() (WordPress/gutenberg#80657)
- Notes: Sync the sidebar selection to the inline marker under the caret (WordPress/gutenberg#80610)
- Writing flow: use isMultiSelecting for shift+click (WordPress/gutenberg#80286) (WordPress/gutenberg#80726)
- Block supports: Return from layout support before resolving global settings (WordPress/gutenberg#80771)
- Notes: Report save success consistently from note actions (WordPress/gutenberg#80748)
- Dynamic Gallery: Rename toolbar button to Detach and add a modal explaining what will happen (WordPress/gutenberg#80727) (WordPress/gutenberg#80774)
- ToolsPanel: Migrate styles to an SCSS Module (WordPress/gutenberg#80445) (WordPress/gutenberg#80800)
- Add a responsiveEditingEnabled editor setting to hide the Responsive styles option (WordPress/gutenberg#80814)
- iOS: remove jumping hack, add typewriter (WordPress/gutenberg#74596)
- Writing flow: stop the page scrolling on caret moves within blocks taller than the viewport (WordPress/gutenberg#80708)
- Global Styles: Put the inheritance UI behind a Gutenberg experiment (… (WordPress/gutenberg#80818)
- Notes: Cancel in-flight hover highlight when focus leaves a note thread (WordPress/gutenberg#80752)
- Block Editor: Try to fix typing performance regression (WordPress/gutenberg#80507)
- List Block: Preserve ordered type on indent (WordPress/gutenberg#75353)
- Make editableRoot a private block setting Symbol, not a public support (WordPress/gutenberg#80820)
- Fix cursor position during forward delete of empty blocks (WordPress/gutenberg#80827)
- Navigation: Fixes `aria-expanded` not updating on hover submenu inside overlay (WordPress/gutenberg#80828)
- Remove redundant @jest-environment jsdom pragma and lint against it (WordPress/gutenberg#80676)
- View config: reject shape-mismatched merges, define empty-array semantics, strip nulls from appended members (WordPress/gutenberg#80829)
- Editor: leave undo to the browser in fields that handle their own undo (WordPress/gutenberg#80768)
- Fix: New route-based admin pages are empty when no JS (WordPress/gutenberg#80839)

Props wildworks.
See #65529.
Built from https://develop.svn.wordpress.org/trunk@62896


git-svn-id: http://core.svn.wordpress.org/trunk@62163 1a063a9b-81f0-0310-95a4-ce76da25c4cd
@jonathanbossenger jonathanbossenger removed the Backport to Gutenberg RC Pull request that needs to be backported to a Gutenberg release candidate (RC) label Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backported to WP Core Pull request that has been successfully merged into WP Core [Feature] Client Side Media Media processing in the browser with WASM [Status] In Progress Tracking issues with work in progress [Type] Bug An existing feature does not function as intended

Projects

Development

Successfully merging this pull request may close these issues.

Media library previews broken for offloaded media: crossorigin forced onto IMG in media templates

3 participants

Sponsor
SponsoredKunjungi sekarang
Promo