Skip to content

fix(chat-widget): clickjacking, stale-bundle, and withdraw-race hardening#785

Merged
bussyjd merged 1 commit into
integration/v0.14.0-rc0from
fix/chat-widget-hardening
Jul 16, 2026
Merged

fix(chat-widget): clickjacking, stale-bundle, and withdraw-race hardening#785
bussyjd merged 1 commit into
integration/v0.14.0-rc0from
fix/chat-widget-hardening

Conversation

@bussyjd

@bussyjd bussyjd commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

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

…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
bussyjd merged commit b365dfd into integration/v0.14.0-rc0 Jul 16, 2026
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
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