fix(extension): fail closed on borrow confirmation#16
Open
NianJiuZst wants to merge 5 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem this solves
The tab-borrow flow was presented as an explicit per-tab authorization gate, but several fallback paths treated the absence of a denial as approval. The in-page overlay automatically allowed a request when its countdown completed. The background coordinator also returned
truewhen no injectable user window existed, when the content script never replied before the timeout, and when a reply was missing or malformed.As a result, a user who did nothing could still have a pre-existing tab moved into the Agent Window. The weakest runtime path was also the most privileged outcome: failures in the confirmation UI, messaging, or notification delivery silently authorized the borrow instead of preserving the user's current browser state.
This contradicted the extension's privacy contract and made it impossible to distinguish an intentional Allow click from a timeout or broken UI path. Existing tests explicitly asserted the old fail-open outcomes, so this needed a behavior change rather than only additional coverage.
How this fixes it
The authorization decision is now fail-closed end to end:
falseimmediately;false;false;{ type: "borrow-response", allowed: true }reply grants access;requireInteractionso Chrome is less likely to hide the explicit fallback before the user acts.The notification Allow button remains a valid explicit authorization path when content-script messaging fails. The timeout still guarantees that the agent call eventually completes, but completion no longer changes browser state without consent.
The English and Chinese countdown text now states that the request expires or is automatically denied, matching the actual result.
User impact
Borrowing continues to work when the user deliberately clicks Allow in either the in-page overlay or the Chrome notification. Clicking Deny, ignoring the request, losing the content-script connection, closing the confirmation surface, or hitting a restricted page all leave the tab where it was.
Automation that previously relied on passive timeout approval will now receive the existing cancelled result and must ask the user to approve the borrow. This is intentional: unattended automation can create or use Agent Window tabs without weakening the authorization boundary around pre-existing user tabs.
Validation
corepack pnpm --filter @browser-skill/extension testcorepack pnpm --filter @browser-skill/extension compilegit diff --checkCI Baseline Compatibility
This branch also carries the one-line Biome 2.4 formatter output for
apps/extension/vitest.config.ts. The same formatting mismatch currently fails the Frontend job onupstream/main; this minimal compatibility commit is intentionally separate from the functional fix and lets this PR run the repository CI suite to completion.CI Reliability Follow-up
GitHub Actions exposed a pre-existing test-only port allocation race: integration helpers probed an ephemeral port, released it, and then asked the daemon to bind the same number, allowing another process to claim it in between. The resulting
Address already in usefailure was unrelated to the functional changes. The PR now lets each daemon bind port0directly and reads the assigned address from its handle, removing the TOCTOU window across all affected integration helpers.