feat: Selective Allow for cross-origin local navigation (#57)#86
Merged
Conversation
When an external page links to a literal local address, prompt on main_frame navigations instead of silently blocking. Allow Once is session-only; Always Allow persists origin→destination pairs. Hardens the allow path by validating that originalUrl is local and matches the displayed destination, reuses the cancelled tab via tabs.update, and dedupes in-flight prompts per origin/destination. Closes #57. Supersedes #74. Co-authored-by: Hacks and Hops <ACK-J@users.noreply.github.com>
Document the manual check in the README so reviewers can exercise the main_frame prompt from a non-local origin. Co-authored-by: Hacks and Hops <ACK-J@users.noreply.github.com>
Defer opening the decision UI outside the blocking webRequest stack, fall back to a tab if the popup window fails, and show a notification so the prompt is not easy to miss. Clarify in README/TestPortScans that this UI is not the toolbar popup. Co-authored-by: Hacks and Hops <ACK-J@users.noreply.github.com>
Clear pending when the decision window/tab is closed so chrome-dismiss cannot permanently suppress re-prompts. Bind Allow Once/Always to a server-issued promptId and the stored pending record instead of client-supplied origin. Keep pending if only the notification fails, clear it when validation rejects, and key file:// initiators by path. Co-authored-by: Hacks and Hops <ACK-J@users.noreply.github.com>
Collapse pending tracking to one map, hardcode the decision page path, and stop mirroring Always Allow into the session set so settings removals take effect immediately. Require a bound UI id before keeping pending, update the latest blocked URL/tab while a prompt is open, and revoke any leftover session allows when the persisted list changes. Co-authored-by: Hacks and Hops <ACK-J@users.noreply.github.com>
Use atomic ensurePendingPrompt so concurrent navigations share one promptId/UI. Key blob/about initiators by full href, refuse data: URLs for selective allow, and drop unused tabId from the decision page URL. Co-authored-by: Hacks and Hops <ACK-J@users.noreply.github.com>
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.
Problem
Clicking a link from an internet page to a local address (e.g.
http://localhost:8080) is treated as a port scan becausewebRequestreports the external page asoriginUrl. That breaks legitimate workflows (Proxmox consoles, VPN dashboards, local dev links in docs).Closes #57. Supersedes #74 (new implementation on current
main, not a rebase of that draft).Solution
For
main_framenavigations to literal local/private URLs, open a Selective Allow popup instead of silently blocking:Set, cleared on restart){ origin, destination }undercross_origin_allowlistSaved pairs are manageable from the settings page.
Subresources (
fetch/ XHR / iframes) and DNS-rebinding style portscans remain on the silent block + badge path.Review fixes vs #74
originalUrlis local andhostmatchesdestinationbefore navigate/persisttabs.update(fallback totabs.create)origin|destinationpagepath traversal inopenSelectiveAllowPopuprequestFilter.jsarchitecture (no conflict withmain)Test plan
npm test(641 passed)http://localhost:8080→ popup appears