Skip to content

Add passkey, WebAuthn, and FIDO2 support to browser pane#2660

Merged
austinywang merged 5 commits intomainfrom
issue-2657-passkeys-webauthn
Apr 7, 2026
Merged

Add passkey, WebAuthn, and FIDO2 support to browser pane#2660
austinywang merged 5 commits intomainfrom
issue-2657-passkeys-webauthn

Conversation

@austinywang
Copy link
Copy Markdown
Contributor

@austinywang austinywang commented Apr 7, 2026

Implements full passkey / WebAuthn / FIDO2 support for the cmux browser pane.

Refs umbrella issue: #2657
Also covers:

What changed:

  • Request browser passkey authorization through AuthenticationServices for trustworthy main-frame WKWebView navigations in both browser tabs and auth popups.
  • Add the com.apple.developer.web-browser.public-key-credential entitlement to the app signing path, while keeping embedded CLI/helper binaries on a narrower entitlement set.
  • Add the Bluetooth privacy usage description needed for cross-device / phone passkey handoff.
  • Add unit coverage for trustworthy-origin and authorization-gating behavior.

This intentionally keeps WebKit handling native navigator.credentials WebAuthn flows instead of reimplementing them in JavaScript/native glue. That aligns cmux with Apple's browser-app passkey model for platform passkeys, cross-device handoff, hardware security keys, and enterprise SSO step-up flows.

Local tests were not run per repo policy.


Note

Medium Risk
Introduces new passkey authorization prompting and adds the com.apple.developer.web-browser.public-key-credential entitlement, plus updates CI/release signing paths; mistakes could break login flows or macOS code-signing/notarization behavior.

Overview
Enables passkey/WebAuthn support in the embedded browser by requesting ASAuthorizationWebBrowserPublicKeyCredentialManager authorization on trustworthy main-frame navigations (HTTPS or loopback HTTP) in both the main browser panel and auth popups, with session-level gating to avoid repeated prompts.

Updates macOS packaging/signing to include the new com.apple.developer.web-browser.public-key-credential app entitlement, splits entitlements so embedded CLI/helper binaries use cmux.embedded.entitlements, and adds a CI/script check (scripts/assert-passkey-entitlement.sh) to fail builds if the signed app is missing the entitlement.

Adds the required NSBluetoothAlwaysUsageDescription (localized) for cross-device passkey flows, and adds unit tests covering trustworthy-origin detection and authorization-request conditions.

Reviewed by Cursor Bugbot for commit a767c32. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Adds passkey/WebAuthn/FIDO2 to the in‑app browser so users can sign in with platform passkeys, cross‑device handoff, and hardware security keys in tabs and auth popups. Prompts for passkey access only on trustworthy main‑frame navigations. Addresses #2657 (also #124, #1056, #1278).

  • New Features

    • Enable passkeys via WKWebView (WebKit handles navigator.credentials).
    • Request authorization only on HTTPS and loopback main‑frame navigations, including cmux-loopback.localtest.me; single prompt per session.
    • Add com.apple.developer.web-browser.public-key-credential to app entitlements; new cmux.embedded.entitlements for CLI/helpers.
    • Add NSBluetoothAlwaysUsageDescription with expanded localizations.
  • Bug Fixes

    • Skip the system passkey prompt during automated UI tests to prevent CI timeouts.
    • Share the passkey authorization manager with auth popups; redact debug logs to scheme/host only.
    • Fix signing order and verify the passkey entitlement via scripts/assert-passkey-entitlement.sh in release/nightly and scripts/build-sign-upload.sh.
    • Improve scripts/reload.sh to prefer an Apple Development identity for tagged builds, falling back to ad‑hoc with a clear note if not.
    • Add/extend tests for origin trust, prompt gating, loopback alias handling, and URL redaction.

Written for commit 6458077. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • WebAuthn passkey support added to the embedded browser for secure sign-ins; authorization limited to HTTPS and loopback/localhost origins.
  • Privacy / Permissions

    • Bluetooth access enabled to support cross-device passkey authentication.
  • Localization

    • Added localized Bluetooth usage descriptions (multiple locales, including English and Japanese).
  • Tests

    • Added unit tests validating passkey origin and authorization logic.
  • Chores

    • Refined app signing flow and added an entitlement verification step to ensure passkey entitlement is present.

Follow-up: CI fix and review responses (commit 6458077)

  • CI: testCmdFFocusesBrowserFindFieldAfterCmdDCmdLNavigation was timing out because the new passkey authorization request, triggered on the first main-frame navigation, opened a system permission dialog that blocked the main thread. Skip the prompt under automated UI tests via SessionRestorePolicy.isRunningUnderAutomatedTests().
  • CodeRabbit (BrowserPanel): treat cmux-loopback.localtest.me (and subdomains) as a loopback host so WebAuthn works in remote workspaces where local pages are proxied through that alias.
  • CodeRabbit (BrowserPanel): redact passkey debug logs to log scheme/host only via a new redactedURLDescription(for:) helper, avoiding leaks of OIDC state, auth codes, or user identifiers.
  • Greptile / CodeRabbit (InfoPlist.xcstrings): add the broader privacy-prompt locale set for NSBluetoothAlwaysUsageDescription (zh-Hans, zh-Hant, ko, de, es, fr, it, da, pl, ru, bs, ar, nb, pt-BR, th, tr) so non-English builds do not fall back to English in the macOS Bluetooth permission dialog.
  • Cubic / CodeRabbit (workflows): verified the codesign order in release.yml, nightly.yml, and scripts/build-sign-upload.sh is already correct (CLI → helper → app, no --deep on the outer sign). The bot reports were inaccurate.
  • CodeRabbit (reload.sh): verified the codesign step already runs after the helper-binary copy and no longer suppresses failures (fixed in commit a767c32).

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 7, 2026

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

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Apr 7, 2026 6:15am

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai bot commented Apr 7, 2026

This review could not be run because your cubic account has exceeded the monthly review limit. If you need help restoring access, please contact contact@cubic.dev.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 7, 2026

📝 Walkthrough

Walkthrough

Adds passkey/WebAuthn authorization prompting for trustworthy navigations, separates app vs embedded entitlements and new entitlement files, updates signing workflows/scripts to use and assert the passkey entitlement, adds Bluetooth usage localization, and adds unit tests and a validation script.

Changes

Cohort / File(s) Summary
CI/CD Workflows & Signing Scripts
/.github/workflows/nightly.yml, /.github/workflows/release.yml, scripts/build-sign-upload.sh, scripts/reload.sh
Split single entitlements var into APP_ENTITLEMENTS and EMBEDDED_ENTITLEMENTS; sign embedded binaries with embedded entitlements and sign app bundle with app entitlements (removed prior --deep app invocation); add post-sign assertion ./scripts/assert-passkey-entitlement.sh; reload.sh now prefers identity-based signing with explicit entitlements and falls back to ad-hoc when identities absent.
Entitlements Files
cmux.entitlements, cmux.embedded.entitlements
Add com.apple.developer.web-browser.public-key-credential = true to cmux.entitlements; add cmux.embedded.entitlements (disable library validation, allow unsigned-exec-memory, allow JIT, camera, audio-input, Apple Events) for embedded executables.
Browser Passkey Integration
Sources/Panels/BrowserPanel.swift, Sources/Panels/BrowserPopupWindowController.swift
Import AuthenticationServices; add BrowserPasskeyAuthorizationSupport and BrowserPasskeyAuthorizationManager singleton; trigger authorization request for main-frame navigations when URL is potentially trustworthy; include debug/redacted URL logging.
Localization & Info plist
Resources/Info.plist, Resources/InfoPlist.xcstrings
Add NSBluetoothAlwaysUsageDescription and localized strings (en, ja, and many others) explaining Bluetooth use for cross-device passkey sign-in.
Tests
cmuxTests/BrowserConfigTests.swift
Add BrowserPasskeyAuthorizationSupportTests validating trustworthy-origin detection, authorization-decision logic across states/flags, and redacted URL formatting.
Validation Script
scripts/assert-passkey-entitlement.sh
New executable that inspects an app bundle’s codesigned entitlements and fails if com.apple.developer.web-browser.public-key-credential is not true.

Sequence Diagram

sequenceDiagram
    participant WV as WebView
    participant ND as BrowserNavigationDelegate
    participant PM as BrowserPasskeyAuthorizationManager
    participant ASAuth as ASAuthorizationWebBrowserPublicKeyCredentialManager
    participant System as System/User

    WV->>ND: webView(decidePolicyFor: navigationAction)
    ND->>ND: ensure main-frame & extract URL
    ND->>PM: requestAuthorizationIfNeeded(url, source)
    PM->>PM: check trust, auth state, pending task, session prompt
    alt Should request authorization
        PM->>ASAuth: requestAuthorizationForPublicKeyCredentials()
        ASAuth->>System: show system prompt
        System-->>ASAuth: grant / deny
        ASAuth-->>PM: result/state
    else Skip request
        PM->>PM: no-op / skip
    end
    PM-->>ND: authorization complete/skip
    ND->>WV: allow navigation
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

codex

Poem

🐰 I hopped through keys and tiny shells,

split the grants and rang the bells.
Passkeys nod on trusted shores,
Bluetooth sings and tests keep score —
a joyful rabbit signs and dwells.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% 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
Title check ✅ Passed Title clearly and concisely summarizes the main feature addition (passkey/WebAuthn/FIDO2 support) as the primary change across the browser pane modifications.
Description check ✅ Passed The PR description comprehensively covers the changes, objectives, and testing approach with detailed sections on implementation details, design rationale, and follow-up fixes.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-2657-passkeys-webauthn

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 7, 2026

Greptile Summary

This PR adds passkey/WebAuthn/FIDO2 support to the cmux browser pane by wiring ASAuthorizationWebBrowserPublicKeyCredentialManager into both the main browser and popup navigation delegates, scoped to potentially-trustworthy origins (HTTPS or loopback HTTP). Entitlement scoping is correct: com.apple.developer.web-browser.public-key-credential is added to cmux.entitlements but deliberately excluded from cmux.embedded.entitlements, and the CI/signing pipelines have been updated consistently. The NSBluetoothAlwaysUsageDescription for cross-device passkey handoff only ships en and ja translations while the rest of the project supports 16+ locales.

Confidence Score: 5/5

Safe to merge; all remaining findings are P2 localization gaps.

The passkey authorization logic is correct, entitlement scoping is intentional, task cleanup is handled, and unit tests cover the core decision logic. The only finding is a missing translation for NSBluetoothAlwaysUsageDescription — a localization gap, not a correctness issue.

Resources/InfoPlist.xcstrings — add the missing locale translations for NSBluetoothAlwaysUsageDescription.

Important Files Changed

Filename Overview
Sources/Panels/BrowserPanel.swift Adds BrowserPasskeyAuthorizationSupport enum and BrowserPasskeyAuthorizationManager singleton; trustworthy-origin detection and rate-limited authorization logic are correct.
Sources/Panels/BrowserPopupWindowController.swift Adds requestAuthorizationIfNeeded in PopupNavigationDelegate for popup main-frame navigations, consistent with main browser behavior.
cmux.entitlements Adds com.apple.developer.web-browser.public-key-credential to the main app entitlements.
cmux.embedded.entitlements Intentionally excludes the passkey entitlement; correct narrower scope for CLI/helper binaries.
cmuxTests/BrowserConfigTests.swift New BrowserPasskeyAuthorizationSupportTests covers isPotentiallyTrustworthy and shouldRequestAuthorization with behavioral test cases.
Resources/Info.plist Adds NSBluetoothAlwaysUsageDescription for cross-device passkey Bluetooth handoff.
Resources/InfoPlist.xcstrings Adds NSBluetoothAlwaysUsageDescription but only en/ja translations; all other keys in this file have 16+ locales.
.github/workflows/nightly.yml Updates codesigning to two-tier entitlements: app uses cmux.entitlements, CLI/helper use cmux.embedded.entitlements.
.github/workflows/release.yml Same two-tier entitlement signing update as nightly.yml.
scripts/build-sign-upload.sh Correct two-tier codesign pattern: app gets full entitlements, CLI/ghostty get narrower embedded entitlements.
scripts/reload.sh Applies main app entitlements to debug builds correctly.

Sequence Diagram

sequenceDiagram
    participant Nav as WKNavigationDelegate
    participant Mgr as BrowserPasskeyAuthorizationManager
    participant Support as BrowserPasskeyAuthorizationSupport
    participant AS as ASAuthorizationWebBrowserPublicKeyCredentialManager

    Nav->>Mgr: requestAuthorizationIfNeeded(url, source)
    Mgr->>AS: authorizationStateForPlatformCredentials
    AS-->>Mgr: state
    Mgr->>Support: shouldRequestAuthorization(url, state, pending, prompted)
    Support->>Support: isPotentiallyTrustworthy(url)
    Support-->>Mgr: true / false
    alt should request
        Mgr->>Mgr: didPromptThisSession = true
        Mgr->>AS: requestAuthorizationForPublicKeyCredentials
        AS-->>Mgr: authorized / denied / notDetermined
        Mgr->>Mgr: authorizationTask = nil
        alt result == notDetermined
            Mgr->>Mgr: didPromptThisSession = false
        end
    end
Loading

Reviews (1): Last reviewed commit: "Fix popup access to shared passkey autho..." | Re-trigger Greptile

Comment on lines +5 to +20
"NSBluetoothAlwaysUsageDescription": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "cmux uses Bluetooth for cross-device passkey sign-in in embedded browser authentication flows."
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "cmux は内蔵ブラウザの認証フローでクロスデバイスのパスキーサインインに Bluetooth を使用します。"
}
}
}
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.

P2 NSBluetoothAlwaysUsageDescription missing locale translations

This new key only includes en and ja translations, but every other key in this file (NSMicrophoneUsageDescription, New $(PRODUCT_NAME) Workspace Here, etc.) carries 16 locales (zh-Hans, zh-Hant, ko, de, es, fr, it, da, pl, ru, bs, ar, nb, pt-BR, th, tr). Users on those locales will see the English fallback in the macOS Bluetooth permission dialog when a cross-device passkey flow is triggered.

Copy link
Copy Markdown

@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: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/nightly.yml:
- Around line 396-408: The codesigning order should sign embedded binaries first
and then sign the app without --deep: for each APP_PATH (using APP_ENTITLEMENTS,
EMBEDDED_ENTITLEMENTS, CLI_PATH, HELPER_PATH), run codesign on CLI_PATH and
HELPER_PATH first using --force --options runtime --timestamp --sign
"$APPLE_SIGNING_IDENTITY" --entitlements "$EMBEDDED_ENTITLEMENTS", then sign the
top-level APP_PATH last using --force --options runtime --timestamp --sign
"$APPLE_SIGNING_IDENTITY" --entitlements "$APP_ENTITLEMENTS" (omit the --deep
flag); keep the existing file-existence checks for CLI_PATH and HELPER_PATH and
preserve the same flags otherwise.

In `@Resources/InfoPlist.xcstrings`:
- Around line 5-20: The NSBluetoothAlwaysUsageDescription entry is missing the
full set of localized keys; update the NSBluetoothAlwaysUsageDescription
stringUnit to include the same locale list used by
NSCameraUsageDescription/NSMicrophoneUsageDescription (add the missing locale
keys such as de, fr, es, it, ko, zh-Hans, zh-Hant, etc.), using the existing
English value as the fallback for lower-confidence locales where you don't have
translations, and ensure each added locale follows the same structure
("localizations" -> "<locale>" -> "stringUnit" -> { "state": "translated" or
"untranslated", "value": "<text>" }) to match the catalog format.

In `@scripts/build-sign-upload.sh`:
- Around line 97-103: Sign embedded executables (CLI_PATH and HELPER_PATH) first
using SIGN_HASH and EMBEDDED_ENTITLEMENTS if they exist, then sign the app
bundle (APP_PATH) last using SIGN_HASH and APP_ENTITLEMENTS without the --deep
flag; this ensures you don’t reseal the parent after signing nested binaries
(remove --deep from the codesign call that targets APP_PATH and move that call
to after the conditional codesign calls for CLI_PATH and HELPER_PATH).

In `@scripts/reload.sh`:
- Line 433: The codesign invocation that signs TAG_APP_PATH with
cmux.entitlements should be moved so it runs after the helper binaries (cmuxd
and ghostty) are copied into Contents/Resources/bin (i.e., after the copy steps
that mutate the bundle), and the redirection/silencing (the >/dev/null 2>&1 ||
true) must be removed so any codesign failures surface; update the script to
call /usr/bin/codesign --force --sign - --timestamp=none
--generate-entitlement-der --entitlements "$PWD/cmux.entitlements"
"$TAG_APP_PATH" after the helper-copy logic and allow non-zero exit to fail the
script or log the error.

In `@Sources/Panels/BrowserPanel.swift`:
- Around line 1825-1842: The debug logging in BrowserPanel.swift currently uses
url?.absoluteString (see variables requestURL and calls to dlog in the passkey
authorization skip and begin branches), which can leak OIDC state, auth codes,
or user identifiers; change these dlog calls to avoid logging the full URL by
logging only non-sensitive metadata such as url?.host (or scheme + host), a
redacted placeholder (e.g., "<redacted_url>"), and a byte/length indicator if
useful, and keep the rest of the fields (source, state.cmuxDebugName,
pending/prompted) unchanged; update both occurrences around the passkey
authorization skip and begin blocks (and the similar 1861-1865 section) to use
the redacted/origin value instead of absoluteString.
- Around line 1763-1777: isLoopbackHost(_: ) currently only recognizes
localhost, ::1 and 127.* but misses the remote loopback alias used by
remoteProxyLoopbackAliasURL(for:). Update isLoopbackHost to also treat the
remote loopback alias host (e.g. "cmux-loopback.localtest.me") and its
subdomains as loopback: add checks for normalized ==
"cmux-loopback.localtest.me" and/or
normalized.hasSuffix(".cmux-loopback.localtest.me"). Keep existing logic
(localhost, .localhost, ::1, 127.*) and ensure you reference the same
normalizedHost(_) usage in this function.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dfe8a62d-d7df-4a70-b19c-8559b17a3706

📥 Commits

Reviewing files that changed from the base of the PR and between 4daa412 and 81f352b.

📒 Files selected for processing (11)
  • .github/workflows/nightly.yml
  • .github/workflows/release.yml
  • Resources/Info.plist
  • Resources/InfoPlist.xcstrings
  • Sources/Panels/BrowserPanel.swift
  • Sources/Panels/BrowserPopupWindowController.swift
  • cmux.embedded.entitlements
  • cmux.entitlements
  • cmuxTests/BrowserConfigTests.swift
  • scripts/build-sign-upload.sh
  • scripts/reload.sh

Copy link
Copy Markdown

@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.

♻️ Duplicate comments (1)
scripts/reload.sh (1)

439-445: ⚠️ Potential issue | 🟠 Major

Re-sign still happens before bundle mutation, and failures are still masked.

At Line 441/444, the app is signed before Lines 481-488 copy cmuxd/ghostty into the bundle, which invalidates the seal. Also, >/dev/null 2>&1 || true hides signing failures, so entitlement regressions are silent.

Suggested fix (move signing after helper copy, fail loud)
-    APPLE_DEVELOPMENT_IDENTITY="$(find_apple_development_identity || true)"
-    if [[ -n "${APPLE_DEVELOPMENT_IDENTITY:-}" ]]; then
-      /usr/bin/codesign --force --sign "$APPLE_DEVELOPMENT_IDENTITY" --timestamp=none --generate-entitlement-der --entitlements "$PWD/cmux.entitlements" "$TAG_APP_PATH" >/dev/null 2>&1 || true
-    else
-      echo "No Apple Development signing identity found; local tagged app will launch without passkey entitlements."
-      /usr/bin/codesign --force --sign - --timestamp=none --generate-entitlement-der "$TAG_APP_PATH" >/dev/null 2>&1 || true
-    fi
+    :
@@
 if [[ -x "$GHOSTTY_HELPER_SRC" ]]; then
   BIN_DIR="$APP_PATH/Contents/Resources/bin"
   mkdir -p "$BIN_DIR"
   cp "$GHOSTTY_HELPER_SRC" "$BIN_DIR/ghostty"
   chmod +x "$BIN_DIR/ghostty"
 fi
+
+if [[ -n "$TAG" && -d "$APP_PATH" ]]; then
+  APPLE_DEVELOPMENT_IDENTITY="$(find_apple_development_identity || true)"
+  if [[ -n "${APPLE_DEVELOPMENT_IDENTITY:-}" ]]; then
+    /usr/bin/codesign --force --sign "$APPLE_DEVELOPMENT_IDENTITY" --timestamp=none --generate-entitlement-der --entitlements "$PWD/cmux.entitlements" "$APP_PATH"
+  else
+    echo "No Apple Development signing identity found; local tagged app will launch without passkey entitlements."
+    /usr/bin/codesign --force --sign - --timestamp=none --generate-entitlement-der "$APP_PATH"
+  fi
+fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/reload.sh` around lines 439 - 445, The current codesign step runs
before the helper binaries are copied (so later bundle mutations break the
signature) and its failures are silenced; move the entire codesign block that
uses APPLE_DEVELOPMENT_IDENTITY and TAG_APP_PATH to execute after the section
that copies cmuxd and ghostty into the app bundle, and remove the "|| true" (and
avoid redirecting stderr/stdout to /dev/null) so any codesign failure causes the
script to fail loudly; ensure both the branch that signs with
"$APPLE_DEVELOPMENT_IDENTITY" and the fallback branch that signs with "-" are
relocated and behave the same (no suppression) so entitlement/signing
regressions surface immediately.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@scripts/reload.sh`:
- Around line 439-445: The current codesign step runs before the helper binaries
are copied (so later bundle mutations break the signature) and its failures are
silenced; move the entire codesign block that uses APPLE_DEVELOPMENT_IDENTITY
and TAG_APP_PATH to execute after the section that copies cmuxd and ghostty into
the app bundle, and remove the "|| true" (and avoid redirecting stderr/stdout to
/dev/null) so any codesign failure causes the script to fail loudly; ensure both
the branch that signs with "$APPLE_DEVELOPMENT_IDENTITY" and the fallback branch
that signs with "-" are relocated and behave the same (no suppression) so
entitlement/signing regressions surface immediately.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4a0e7c09-6420-409a-adb2-70dd64b39cbc

📥 Commits

Reviewing files that changed from the base of the PR and between 81f352b and 7b86496.

📒 Files selected for processing (1)
  • scripts/reload.sh

- Skip the system passkey authorization prompt when running under
  automated UI tests; the dialog blocked the main thread and caused
  testCmdFFocusesBrowserFindFieldAfterCmdDCmdLNavigation to time out.
- Treat the cmux-loopback.localtest.me alias (and subdomains) as a
  loopback host so WebAuthn works in remote workspaces where local
  pages are proxied through that hostname.
- Redact passkey authorization debug logs to log scheme/host only,
  avoiding leaks of OIDC state, auth codes, or user identifiers.
- Add the broader privacy-prompt locale set for
  NSBluetoothAlwaysUsageDescription so non-English builds do not fall
  back to English in the macOS Bluetooth permission dialog.
- Update BrowserPasskeyAuthorizationSupport tests to cover the new
  loopback alias and the URL-redaction helper.
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is kicking off a free cloud agent to fix this issue. This run is complimentary, but you can enable autofix for all future PRs in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6458077. Configure here.

// WKWebView handles WebAuthn itself for browser apps; this support code only
// determines when cmux should request browser passkey access from macOS.
enum BrowserPasskeyAuthorizationSupport {
static let remoteLoopbackAliasHost = "cmux-loopback.localtest.me"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicate loopback alias host constant risks future drift

Low Severity

The magic string "cmux-loopback.localtest.me" is now defined as BrowserPasskeyAuthorizationSupport.remoteLoopbackAliasHost in addition to the existing BrowserPanel.remoteLoopbackProxyAliasHost (and a third copy in Workspace). If one copy is updated without the others, the passkey trustworthiness check and the proxy rewriting logic would silently disagree on which hosts are treated as loopback, creating a security-relevant inconsistency.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6458077. Configure here.

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
Sources/Panels/BrowserPanel.swift (1)

1734-1736: Share the loopback alias constant.

The remote-proxy rewrite and passkey trust check both key off this exact value, but the string now lives in two separate constants in the same file. Keeping one source of truth would reduce the chance that those paths drift apart again.

♻️ Proposed refactor
+private let browserRemoteLoopbackAliasHost = "cmux-loopback.localtest.me"
+
 enum BrowserPasskeyAuthorizationSupport {
-    static let remoteLoopbackAliasHost = "cmux-loopback.localtest.me"
+    static let remoteLoopbackAliasHost = browserRemoteLoopbackAliasHost
@@
 final class BrowserPanel: Panel, ObservableObject {
-    private static let remoteLoopbackProxyAliasHost = "cmux-loopback.localtest.me"
+    private static let remoteLoopbackProxyAliasHost = browserRemoteLoopbackAliasHost
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Panels/BrowserPanel.swift` around lines 1734 - 1736, The duplicate
loopback alias string is defined twice; consolidate it to a single shared
constant by exposing BrowserPasskeyAuthorizationSupport.remoteLoopbackAliasHost
as the single source of truth and replace any other occurrences or duplicate
constants (e.g., the remote-proxy rewrite and passkey trust check constants) to
reference BrowserPasskeyAuthorizationSupport.remoteLoopbackAliasHost so both
subsystems use the exact same value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@Sources/Panels/BrowserPanel.swift`:
- Around line 1734-1736: The duplicate loopback alias string is defined twice;
consolidate it to a single shared constant by exposing
BrowserPasskeyAuthorizationSupport.remoteLoopbackAliasHost as the single source
of truth and replace any other occurrences or duplicate constants (e.g., the
remote-proxy rewrite and passkey trust check constants) to reference
BrowserPasskeyAuthorizationSupport.remoteLoopbackAliasHost so both subsystems
use the exact same value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9d6133a5-5e8e-4d6d-8bc4-c971f223988d

📥 Commits

Reviewing files that changed from the base of the PR and between a767c32 and 6458077.

📒 Files selected for processing (3)
  • Resources/InfoPlist.xcstrings
  • Sources/Panels/BrowserPanel.swift
  • cmuxTests/BrowserConfigTests.swift
✅ Files skipped from review due to trivial changes (2)
  • Resources/InfoPlist.xcstrings
  • cmuxTests/BrowserConfigTests.swift

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant