Skip to content

Cloudinary media tab broken under WP 7.1 + Chromium ≥ 137: all.js blocked by CORS (crossorigin="anonymous" stamped by wp_set_up_cross_origin_isolation) #1254

Description

@eugenepg

Environment

  • Plugin version: 3.3.6
  • WordPress version: 7.1
  • Browser: Chromium-based, version ≥ 137 (Chrome, Edge, etc.)

Description

The Cloudinary tab in the WP block editor media picker shows a loading spinner indefinitely. Opening DevTools reveals:

Access-Control-Allow-Origin header missing on
https://media-library.cloudinary.com/global/all.js?ver=3.3.6

Uncaught TypeError: cloudinary.openMediaLibrary is not a function
    at n.ready (media-modal.js:101:28)

Root cause

WordPress 7.1 introduced wp_set_up_cross_origin_isolation(), hooked on load-post.php and load-post-new.php (see wp-includes/default-filters.php). On Chromium ≥ 137 it wraps the entire page output in a buffer that:

  1. Sends a Document-Isolation-Policy: isolate-and-credentialless header
  2. Calls wp_add_crossorigin_attributes() on all output, which stamps crossorigin="anonymous" onto every <script src> whose URL is cross-origin (i.e. doesn't start with site_url())

The plugin enqueues all.js from https://media-library.cloudinary.com/global/all.js. That CDN endpoint does not serve an Access-Control-Allow-Origin header. Once the browser sees crossorigin="anonymous" on the tag, it enforces CORS, the request is blocked, window.cloudinary is never populated with openMediaLibrary, and the media tab fails.

Suggested fixes

Option 1 (CDN side): Add Access-Control-Allow-Origin: * to the response headers for https://media-library.cloudinary.com/global/all.js. Simplest change, no plugin update needed.

Option 2 (plugin side): Bundle all.js inside the plugin and enqueue it as a same-origin asset. wp_add_crossorigin_attributes() only touches cross-origin URLs, so a local copy is never affected. More robust — removes the runtime CDN dependency entirely.

Workaround

We worked around this by intercepting the script_loader_src filter to swap the cloudinary-media-library handle to a locally-served copy of all.js:

add_filter('script_loader_src', function(string $src, string $handle): string {
    if ($handle === 'cloudinary-media-library') {
        return get_template_directory_uri() . '/assets/js/admin/cloudinary-media-library.js';
    }
    return $src;
}, 10, 2);

This resolves the issue but requires maintaining a local snapshot of the widget.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions