Skip to content

@clerk/chrome-extension bundles remote UI script loader, rejected by Chrome Web Store under Manifest V3 #8770

@devlarabar

Description

@devlarabar

Preliminary Checks

Reproduction

n/a

Publishable key

n/a

Description

Package: @clerk/chrome-extension@3.1.32

@clerk/chrome-extension ships a runtime CDN loader that injects @clerk/ui's ui.browser.js from Clerk's servers via a dynamically created <script> tag.

The Chrome Web Store now rejects Manifest V3 extensions that merely contain this code, regardless of whether it ever runs. The extension was rejected for it on June 5 2026 despite the loader never executing (the extension renders no Clerk UI components); I created a plugin that stripped this code at build, re-submitted, and the extension was flagged again on June 6 2026, this time for another piece of Clerk's code.

This is remotely hosted code by Google's definition, and we (extension creators) have no supported way to remove it from the bundle, except for digging for it and stripping it ourselves. Seems as though even URLs flagged as "RHC" in the source maps will trigger Web Store rejection, too.

I believe the offending code lives in @clerk/shared:

Can we get a no-RHC variant of this for the chrome extension? There's already a @clerk/ui/no-rhc, makes sense to drop the remote loader that contradicts it.

Chrome store rejections:

Violation reference ID: Blue Argon
Technical Requirements - Additional Requirements for Manifest V3:
Violation: Including remotely hosted code in a Manifest V3 item.
Violating Content:
Code snippet: assets/App-DOB_oaUF.js: "const w = document.createElement("script"); l && w.setAttribute("crossorigin", l), w.async = r || !1, w.defer = n || !1, w.addEventListener("load", () => { w.remove(), b(w) }), w.addEventListener("error", v => { var S; w.remove(), k((S = v.error) != null ? S : new Error(`failed to load script: ${e}`)) }), w.src = e, w.nonce = u, s == null || s(w), document.body.appendChild(w) })"

Violation reference ID: Blue Argon
Technical Requirements - Additional Requirements for Manifest V3:
Violation: Including remotely hosted code in a Manifest V3 item.
Violating Content:
Code snippet: assets/App-Bl-jAqh8.js: return a || `https://${i_({publishableKey:l,proxyUrl:n,domain:s})}/npm/@clerk/ui@${Z9(r,"1.3.0")}/dist/ui.browser.js`

Potential solution

Adding a build-time gate to loadClerkUIScript should fix the problem (it currently has a runtime-only gate); this is what's already done for loadClerkJSScript.

Other issues related to RHC

I've found some other updates that fix RHC issues (4899, 4886, 7983, 6754, 6179) but not one for this.

Steps to reproduce:

  1. Create a new Chrome extension using Manifest V3
  2. Install and implement @clerk/chrome-extension
  3. Build and submit to Chrome Web Store
  4. Receive rejection due to remote code loading

Expected behavior:

The Clerk authentication should work in Chrome extension without loading remote code.

Actual behavior:

The bundled code contains references to remote URLs, which violates Chrome's MV3 policies.
These URLs appear to be coming from the bundled @clerk/ui package.

Environment

System:
    OS: macOS 26.5
    CPU: (12) arm64 Apple M3 Pro
    Memory: 159.45 MB / 18.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 24.13.0
    Yarn: 1.22.22
    npm: 11.6.2
    pnpm: 10.33.0
    bun: 1.3.14
    Watchman: 2026.03.09.00
  Browsers:
    Chrome: 148.0.7778.216
    Firefox: 147.0.4
    Safari: 26.5
  npmPackages:
    @cipherstash/protect: 10.2.1 => 10.2.1 
    @commitlint/cli: ^19.3.0 => 19.8.1 
    @commitlint/config-conventional: ^19.2.2 => 19.8.1 
    @octokit/rest: ^22.0.1 => 22.0.1 
    @pulumi/pulumi: ^3.150.0 => 3.167.0 
    @sanity/eslint-plugin-i18n: ^1.1.0 => 1.1.0 
    @semantic-release/commit-analyzer: ^13.0.1 => 13.0.1 
    @semantic-release/exec: ^7.1.0 => 7.1.0 
    @semantic-release/github: ^12.0.2 => 12.0.2 
    @semantic-release/npm: ^12.0.1 => 12.0.2 
    @semantic-release/release-notes-generator: ^14.1.0 => 14.1.0 
    @typescript/native-preview: 7.0.0-dev.20260122.4 => 7.0.0-dev.20260122.4 
    @vitest/coverage-v8: ^2.1.9 => 2.1.9 
    concurrently: ^9.1.0 => 9.1.2 
    dependency-cruiser: ^17.3.8 => 17.3.9 
    dotenv-cli: ^11.0.0 => 11.0.0 
    esbuild: 0.19.2 => 0.19.2 
    expo-font: ^14.0.9 => 14.0.9 
    husky: ^9.1.7 => 9.1.7 
    intl-pluralrules: ^1.3.1 => 1.3.1 
    lint-staged: ^16.1.2 => 16.1.2 
    oxfmt: ^0.37.0 => 0.37.0 
    oxlint: ^1.52.0 => 1.56.0 
    semantic-release: ^25.0.2 => 25.0.2 
    slackify-markdown: ^5.0.0 => 5.0.0 
    sst: ^3.19.3 => 3.19.3 
    turbo: ^2.5.6 => 2.5.6 
    typescript: 5.9.3 => 5.9.3 
    zod: ^4.1.12 => 4.1.12

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageA ticket that needs to be triaged by a team member

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions