fix(chat-widget): clickjacking, stale-bundle, and withdraw-race hardening#785
Merged
Merged
Conversation
…ft, and withdraw race - Serve /chat with Content-Security-Policy: frame-ancestors 'self' (new addResponseHeader merges it into the existing ResponseHeaderModifier filter, since Gateway API disallows repeating a core filter type per rule). The page holds a hot session key and signs USDC transfers, so a cross-origin iframe could previously clickjack Connect/Fund/Withdraw/Send. - Add TestChatVendorVersionMatchesBundle: computes sha256 of the embedded chat-vendor.js and asserts chat.html's hardcoded ?v= prefix matches, so a vendor rebuild without a version bump now fails CI instead of silently serving returning visitors the old payment-signing bundle for up to a year (the bundle is cached 1-year immutable). - withdraw() now awaits the transfer receipt (like fund() already does) before declaring success and refreshing, and the withdraw/send guards are now mutual: withdraw() also checks `busy`, and the composer submit handler also checks `withdrawing`, closing the race where a withdrawal and a paid message could spend the same session balance concurrently. Claude-Session: https://claude.ai/code/session_014YjPMViNrZ7zBVgUQzwEKk
bussyjd
added a commit
that referenced
this pull request
Jul 17, 2026
Remove the browser chat widget stack (#752 agent-chat-widget, #762 chat-siwe-session, #785 chat-widget-hardening) from the release candidate. The per-message widget + its browser session wallet are being reworked on top of x402 batch-settlement, so they ship in a later RC rather than rc0. Deletes chat.html / chat-vendor.js / chatwidget.go and the /chat routes, the shared vendor-bundle serving, and the widget tests. Keeps the hostRouteRules refactor (later fixes depend on it) and the verifier paid-route Origin-strip. go build ./... and go test ./... green (39 pkgs ok, 0 fail). NEEDS-RESIGN: committed unsigned due to YubiKey 'invalid format'; re-sign before release. Claude-Session: https://claude.ai/code/session_01PnhCQLz7CHuDBUhWd5xF8v
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.
Chat-widget findings from the PR #756 review. Adds a test enforcing chat.html's ?v= matches the embedded chat-vendor.js sha256 (a forgotten bump otherwise serves returning visitors the old payment-signing bundle for up to a year); serves /chat with frame-ancestors 'self' so the hot-session-key payment UI can't be clickjacked; makes withdraw() await the receipt like fund() and guards the in-flight-payment race.
https://claude.ai/code/session_014YjPMViNrZ7zBVgUQzwEKk