Repository navigation
Harden iframe previews: press reports, service workers, and metadata addresses - #1537
Conversation
The press report a proxied frame posts now selects the pane in passthrough and acknowledges its Session without moving DOM focus: the page shares the shim's origin, so it can post the same message with no click. The shim takes focus from inside for a real press, which also covers a page that cancels the press. A frame out of sight, which no one can click, is not heard, so selecting it cannot hand it focus when its Workspace comes back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…frame proxy The address guard now covers the fixed cloud metadata addresses outside 169.254/16 and reads IPv6 literals as bytes, so a metadata address carried through a transition form (mapped in any spelling, translated, NAT64, 6to4, Teredo, ISATAP) is refused however it is written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A worker registered on a grant's origin outlives the grant and answers the next grant on that port ahead of the proxy and its Clear-Site-Data. The proxy now answers a service worker script fetch with 403 on every grant but a tunneled one, whose page is not at that port. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Focus reaches the embedding document ahead of the report, so testing it needs no new Wall action or visibility gate: a report from a frame without focus now moves nothing, including selection and the terminal's focus. Share one IPv6 parser between the address guard and the network policy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deploying mouseterm with
|
| Latest commit: |
3bc04b3
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e3fdde33.mouseterm.pages.dev |
| Branch Preview URL: | https://iframe-focus-and-proxy-harde.mouseterm.pages.dev |
…y-hardening # Conflicts: # scripts/security-rule-ids.json # scripts/spec-word-budgets.json
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dormouse-bot
left a comment
There was a problem hiding this comment.
The 6to4, Teredo, and ISATAP branches of ipv4sCarriedByIPv6 refuse addresses that cannot reach a metadata endpoint, so they add bit math and tests for no trigger. Those three are tunnels, not translators. A packet to 2002:a9fe:a9fe:: is sent to 169.254.169.254 as IPv6 inside IPv4 protocol 41 (RFC 3056 §5), and ISATAP does the same (RFC 5214). A Teredo address is reached over UDP at the client's mapped address (RFC 4380), and the server address in the prefix never carries data. The IPv4 host at the embedded address has to decapsulate and speak IPv6 itself, and an IMDS HTTP endpoint doesn't, so no TCP connection to it on port 80 ever forms. Only translation (mapped/SIIT, NAT64 at any of its prefix lengths) ends an IPv6 connection at an IPv4 service. Those branches are the ones that hold the guard, and they stay.
Dropping the tunnel branches also fixes the claim in the test comment ("hands the embedded address to a router or translator, so the connection ends at the IPv4 address") and in dor-browser.rationale.md, which currently say something the network doesn't do. The PR description's "(… 6to4, Teredo, ISATAP)" would need the same edit. The suggestions below cover the code, tests, and rationale. The '2001:db8::5efe:808:808' row in the does-not-block table can stay or go.
Checked: the four touched test files pass locally (390 tests).
6to4, Teredo, and ISATAP are tunnels: they carry IPv6 inside IPv4 to the embedded address, which has to decapsulate and speak IPv6 itself, so no TCP connection to an HTTP metadata endpoint forms. The guard keeps the forms that name an IPv4 address or reach one through a translator, and the comments and rationale now say that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dormouse-bot
left a comment
There was a problem hiding this comment.
Build & Test is red at this head because of the spec-lint problem the description names: scripts/security-rule-ids.json: S302 is in no security spec and not retired. That clears only once #1535 lands and main is merged in here, so I'm withdrawing the approval until then. The code change itself has no open findings.
CI failed — spec-lint S302 pending #1535
…y-hardening # Conflicts: # scripts/spec-word-budgets.json
…y-hardening # Conflicts: # scripts/spec-word-budgets.json
…y-hardening # Conflicts: # scripts/security-rule-ids.json # scripts/spec-word-budgets.json
…y-hardening # Conflicts: # scripts/spec-word-budgets.json
Three pieces of hardening in the iframe preview.
A frame's press report counts only from the frame holding focus. The shim posts
pointerdownso the Wall can enter a pane it cannot see clicked. The page shares the shim's origin and can post the same message, soIframePanelnow acts on it only whendocument.activeElementis its own frame. A report from any other frame moves nothing: not focus, selection, or mode, and the terminal keeps the keyboard. The shim focuses its own frame before it posts, so a real press still enters the pane, including on a page that cancelsmousedownorpointerdown, which a browser gives no focus. A newS303holds this.docs/specs/security.md-> "Known gaps" gains a line for what no parent can stop: a browser lets a frame focus itself.No service workers on a local preview. A worker stays with its origin after the grant ends and would answer the next grant on that port ahead of the proxy and its
Clear-Site-Data. The proxy now answers a service worker script fetch with403on every grant but a tunneled one. A local PWA previews without its worker.The metadata refusal covers the addresses it claims.
isBlockedAddressnow refuses the fixed cloud metadata addresses outside 169.254/16, and reads IPv6 as bytes so a metadata address named by, or reached through a translator from, an IPv6 literal (mapped in any spelling, compatible, translated, NAT64) is refused however it is written. Tunnel forms (6to4, Teredo, ISATAP) are not read, since a tunnel ends at a host that decapsulates IPv6, not at an HTTP metadata service.ipv6Bytesshares its parser with the network policy's address math, which moved tolib/src/lib/ip-literal.ts.Testing
pnpm testat the root andtsc -binlibpass. Each new test goes red with its fixed line removed.innerdogfood: a report with no click leaves the terminal focused and typing in it; a real click enters the frame, selection follows, and keys reach the page; the same on a page that cancels the press; moving between frame and terminal works both ways.403.Not run: the shipped Tauri and VS Code apps, WebView2, and WebKitGTK.
🤖 Generated with Claude Code