Client-Side Media Everywhere
In one sentence: this plugin gets client-side media processing working in Safari and Firefox, which WordPress otherwise only does in Chrome.
When you upload an image in Chrome, WordPress resizes and compresses it on your own device before it is sent, so less data goes over the wire and your server does much less work. In Safari and Firefox that is switched off, and uploads fall back to the older server-side path. This plugin switches it back on.
There is nothing to configure – activate the plugin and it works. Chrome is unaffected, because WordPress already handles it there.
One thing to know before you install: this works by turning on cross-origin isolation, which is a real security boundary and can affect embeds and third-party media inside the editor. It is worth reading the Tradeoffs section below first.
Why WordPress switches it off:
WordPress 7.1 and Gutenberg include client-side media processing powered by WebAssembly (wasm-vips). This requires cross-origin isolation, which is achieved via Document-Isolation-Policy (DIP) on Chrome 137+.
However, Firefox and Safari do not yet support DIP, and neither does Chrome before 137, so client-side media processing is disabled on those browsers.
This plugin restores support for Firefox and Safari by sending the older COEP/COOP headers (Cross-Origin-Embedder-Policy / Cross-Origin-Opener-Policy) on browsers where DIP is not available.
Under the hood:
- Sends
Cross-Origin-Opener-Policy: same-originandCross-Origin-Embedder-Policy: credentialless(orrequire-corpon Safari) headers in the block editor. - Adds
crossorigin="anonymous"attributes to cross-origin resources. - Adds
credentiallessattribute to iframes so they continue working under COEP. - Filters embed previews for providers that do not support credentialless iframes (Facebook, SmugMug).
Requirements:
- WordPress 6.8+ with the Gutenberg plugin (which provides the client-side media processing feature), or WordPress 7.1+.
- The client-side media processing feature must be enabled (it is on by default in secure contexts).
- HTTPS (or localhost): client-side media processing requires a secure context.
Tradeoffs
Cross-origin isolation is a security boundary. It works by making the browser refuse cross-origin resources that have not opted in, or strip their credentials. That is what unlocks SharedArrayBuffer and wasm-vips, but it is also why Chrome moved to Document-Isolation-Policy: DIP gives the same isolation without imposing these restrictions on the rest of the page.
Only browsers that receive the COEP/COOP headers are affected – Firefox, Safari, and Chrome < 137 – and only on block editor screens (post editor, site editor, block widgets) for users who can upload files. The front-end, the rest of wp-admin, and Chrome 137+ are untouched.
What can break on those screens:
- oEmbed previews. Embeds are iframed. Under
credentialless(Firefox, Chrome < 137) the plugin adds thecredentiallessattribute so they still load, but without cookies – embeds that need a logged-in session render logged-out or not at all. Facebook and SmugMug do not work with credentialless iframes, so their live previews are disabled in the editor and the placeholder is shown instead. Safari does not supportcredentiallessat all, so underrequire-corpany embed whose provider does not send its own COEP header is blocked outright. - Media served from third-party origins. Images, video, audio, and fonts loaded into the editor from a CDN or another domain must opt in with
Cross-Origin-Resource-Policy. Undercredentiallessthey load but without credentials, so anything behind a signed cookie fails. Underrequire-corp(Safari) they are blocked unless the server sends CORP – the plugin addscrossorigin="anonymous"to cross-origin images to give them a CORS path instead, which only helps if the server sendsAccess-Control-Allow-Origin. - Popup-based authentication.
Cross-Origin-Opener-Policy: same-originsevers thewindow.openerlink to cross-origin popups. Plugins that connect to an external service by opening an OAuth popup and waiting for it to call back into the opener will hang. - Plugins that load editor assets cross-origin. Any third-party script, stylesheet, or font pulled into the editor from another origin is subject to the same rules.
- The classic block. The classic block and other TinyMCE-based UIs commonly load third-party assets, and are a frequent place for the failures above to surface.
These are the same constraints the block editor lived with before Chrome shipped Document-Isolation-Policy. If you hit one, suppress the headers with the csme_use_coep_coop filter or deactivate the plugin – media processing then falls back to the server on the affected browsers, which is the behavior without this plugin installed.
