Skip to content

fix(ui): Initial pass for adding RHC guards to ui package#7983

Merged
royanger merged 4 commits intomainfrom
roy/add-remote-code-exclusion-mechanism-to-ui-package
Mar 5, 2026
Merged

fix(ui): Initial pass for adding RHC guards to ui package#7983
royanger merged 4 commits intomainfrom
roy/add-remote-code-exclusion-mechanism-to-ui-package

Conversation

@royanger
Copy link
Member

@royanger royanger commented Mar 4, 2026

Description

clerk-js and shared already exclude remotely hosted code. Core 3 moved ui to its own package, but it is not correctly excluding remotely hosted code even those some guards were in place in the code. This PR adds the mechanism to exclude remotely hosted code and imports the new @clerk/us/no-rhc into <ClerkProvider /> for @clerk/chrome-extension

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new @clerk/ui/no-rhc package variant with streamlined dependencies.
  • Chores

    • Updated chrome extension to use the new UI package variant.
    • Enhanced build validation with new checks.

@changeset-bot
Copy link

changeset-bot bot commented Mar 4, 2026

🦋 Changeset detected

Latest commit: c4100d3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@clerk/chrome-extension Minor
@clerk/ui Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Mar 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Mar 5, 2026 5:17pm

Request Review

@royanger royanger changed the title fix: Initial pass for adding RHC guards to ui package fix(ui): Initial pass for adding RHC guards to ui package Mar 5, 2026
@royanger royanger marked this pull request as ready for review March 5, 2026 17:16
Co-authored-by: Tom Milewski <me@tm.codes>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a new RHC-disabled variant of the @clerk/ui package. The changes add a new "./no-rhc" export entry to package.json with separate build output at dist/no-rhc. A new tsdown build configuration is created that compiles this variant with the BUILD_DISABLE_RHC flag enabled, which causes the loadGIS function in one-tap.ts to short-circuit and skip remote code loading. The chrome-extension package is updated to import from the new @clerk/ui/no-rhc path. A new validation script is integrated into the build process to verify the no-rhc variant contains no remote code, and the search script is extended to scan this new artifact.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately reflects the main change: adding RHC (remotely hosted code) guards to the ui package, which is the core objective described in the PR description.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/search-for-rhc.mjs (1)

27-37: ⚠️ Potential issue | 🔴 Critical

RHC scan can fail open, so this new check may silently pass.

Because of current scanner behavior, Line 30 can report success even when the scan errored: Line 17 runs grep on directories without recursion, and Line 20 treats any non-zero exit code (including grep errors) as "not found". This makes the no-RHC guard unsafe to rely on.

🐛 Proposed fix
 async function asyncSearchRHC(name, search, regex = false) {
   const flag = regex ? 'E' : 'F';
   const cmd = () =>
     targetType === 'directory'
-      ? $`grep -${flag}q --include=\\*.js --include=\\*.mjs ${search} ${target}`
+      ? $`grep -r -${flag}q --include=\\*.js --include=\\*.mjs ${search} ${target}`
       : $`grep -${flag}q ${search} ${target}`;
 
-  if ((await cmd().exitCode) === 0) {
+  const exitCode = await cmd().exitCode;
+  if (exitCode === 0) {
     throw new Error(`Found ${name} related RHC in build output. (Search: \`${search}\`)`);
   }
+  if (exitCode > 1) {
+    throw new Error(`Failed scanning for ${name}. grep exited with code ${exitCode}.`);
+  }
 
   return;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/search-for-rhc.mjs` around lines 27 - 37, The asyncSearchRHC-based
scan can "fail open" because grep is run non-recursively and any grep error is
treated like "not found"; update asyncSearchRHC to invoke grep with recursion
(e.g., -R) and change its child-process handling so that grep exit code 2 (or
any stderr output / execution error) causes the promise to reject (only exit
code 1 should be interpreted as “no match”), then ensure the Promise.allSettled
consumer interprets rejected promises as scan failures rather than successes.
Specifically modify the asyncSearchRHC implementation and its child_process
callbacks to propagate execution errors (reject on code 2 or error), use
recursive grep, and adjust how results from Promise.allSettled are evaluated so
errors don’t silently pass the no-RHC guard.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ui/src/utils/one-tap.ts`:
- Around line 42-44: The branch that returns "undefined as unknown as Google"
when __BUILD_DISABLE_RHC__ is true must be fixed: change the function's return
type to allow undefined (e.g., Google | undefined) or return a safe stub object
instead of force-casting undefined; update the code around the
__BUILD_DISABLE_RHC__ check so it either returns a proper fallback
implementation or an unambiguous undefined/null (no cast) and adjust all callers
of the function (the function that contains the __BUILD_DISABLE_RHC__ branch and
any usages expecting a Google) to handle the optional value accordingly.

---

Outside diff comments:
In `@scripts/search-for-rhc.mjs`:
- Around line 27-37: The asyncSearchRHC-based scan can "fail open" because grep
is run non-recursively and any grep error is treated like "not found"; update
asyncSearchRHC to invoke grep with recursion (e.g., -R) and change its
child-process handling so that grep exit code 2 (or any stderr output /
execution error) causes the promise to reject (only exit code 1 should be
interpreted as “no match”), then ensure the Promise.allSettled consumer
interprets rejected promises as scan failures rather than successes.
Specifically modify the asyncSearchRHC implementation and its child_process
callbacks to propagate execution errors (reject on code 2 or error), use
recursive grep, and adjust how results from Promise.allSettled are evaluated so
errors don’t silently pass the no-RHC guard.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: ecd6d950-d379-4618-a36f-e2aff31b43ed

📥 Commits

Reviewing files that changed from the base of the PR and between 09088ed and c4100d3.

📒 Files selected for processing (8)
  • .changeset/five-carrots-laugh.md
  • packages/chrome-extension/src/react/ClerkProvider.tsx
  • packages/chrome-extension/src/utils/__tests__/clerk-client.test.ts
  • packages/chrome-extension/src/utils/clerk-client.ts
  • packages/ui/package.json
  • packages/ui/src/utils/one-tap.ts
  • packages/ui/tsdown.config.mts
  • scripts/search-for-rhc.mjs

Comment on lines +42 to +44
if (__BUILD_DISABLE_RHC__) {
return undefined as unknown as Google;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Do not return undefined cast as Google in no-RHC builds.

Line 43 creates a type/runtime mismatch (undefined masquerading as Google). This can cause runtime crashes when consumers dereference the result.

🐛 Proposed fix
-async function loadGIS() {
+async function loadGIS(): Promise<Google> {
   if (__BUILD_DISABLE_RHC__) {
-    return undefined as unknown as Google;
+    clerkFailedToLoadThirdPartyScript('Google Identity Services');
   }
   if (!window.google) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/utils/one-tap.ts` around lines 42 - 44, The branch that
returns "undefined as unknown as Google" when __BUILD_DISABLE_RHC__ is true must
be fixed: change the function's return type to allow undefined (e.g., Google |
undefined) or return a safe stub object instead of force-casting undefined;
update the code around the __BUILD_DISABLE_RHC__ check so it either returns a
proper fallback implementation or an unambiguous undefined/null (no cast) and
adjust all callers of the function (the function that contains the
__BUILD_DISABLE_RHC__ branch and any usages expecting a Google) to handle the
optional value accordingly.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 5, 2026

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7983

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7983

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7983

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7983

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7983

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7983

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@7983

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7983

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7983

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7983

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@7983

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7983

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7983

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7983

@clerk/react

npm i https://pkg.pr.new/@clerk/react@7983

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7983

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7983

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7983

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7983

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@7983

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7983

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7983

commit: c4100d3

@royanger royanger merged commit e13fc29 into main Mar 5, 2026
67 of 68 checks passed
@royanger royanger deleted the roy/add-remote-code-exclusion-mechanism-to-ui-package branch March 5, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants