Repository navigation
fix(bridge): harden transports, privacy gates, and envelope guard - #409
Merged
Merged
Conversation
Addresses a full review of the provider-neutral bridge. Security and correctness: - postMessage no longer defaults to targetOrigin '*'. It falls back to the sending page's origin and throws when none can be determined, matching the invariant already enforced in @askable-ui/mcp's page bridge. Broadcasting is now an explicit allowAnyOrigin opt-in. - HTTP headers are normalized through Headers before merging. Object spread silently dropped Headers instances and entry arrays, so an Authorization header supplied in either form never reached the request. - Duplicate transport ids throw instead of silently replacing the earlier transport, and unregister handles delete by identity rather than by id. - Sends use allSettled: a throwing transport becomes an ok:false ack instead of discarding the acks of transports that succeeded. Privacy: - requireRedacted, allowedConsent, and maxEnvelopeBytes gate every send before any transport runs. requireRedacted mirrors @askable-ui/mcp. API: - sendAgentRequest() accepts a ctx.toAgentRequest() payload directly, so apps no longer resolve context twice to reach the bridge. payload.metadata added. - isAskableBridgeEnvelope validates consent and rejects arrays; envelopes from the same major version are accepted so a minor bump does not break every deployed receiver. Exposed as isAskableBridgeVersionSupported(). - Abort signals are honored by every transport and by dispose(); failed HTTP requests report the response body. Docs: - Provider examples use toContextPacketAsync(), the only form that resolves registered context sources into surrounding.sources. - README gains a Bridge section; guide and API pages cover origins, privacy gates, ack semantics, and agent-request interop.
Examples were still pinned to ^0.17.0 while packages shipped 0.17.1, so check-example-askable-versions failed on main and turned static/quality red on every open pull request. Refreshes the npm and pnpm lockfiles alongside the manifests; the pnpm lockfile had drifted two releases behind at 0.16.0.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
@askable-ui/angular
@askable-ui/bridge
@askable-ui/context
@askable-ui/core
@askable-ui/create-app
@askable-ui/mcp
@askable-ui/qwik
@askable-ui/react
@askable-ui/react-native
@askable-ui/solid
@askable-ui/svelte
@askable-ui/vue
@askable-ui/web-component
commit: |
This branch was successfully deployed
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.
Full review of
@askable-ui/bridge(#406) and its interaction with@askable-ui/context,@askable-ui/core, and@askable-ui/mcp. Every finding is addressed here.Security and correctness
postMessageno longer defaults totargetOrigin: '*'. It falls back to the sending page's origin and throws when none can be determined — the same invariant@askable-ui/mcp's page bridge already documents in code ("Never fall back to'*': context packets must not be broadcast to arbitrary origins"), which fix(security): audit fixes — storage masking defaults, page-bridge target origin, CI permissions #362 hardened and this package had reintroduced. Broadcasting is now an explicitallowAnyOriginopt-in.Headersbefore merging.HeadersInitcoversHeadersinstances and entry arrays, and object spread silently drops both — anAuthorizationheader supplied in either form never reached the request.createHttpTransport()calls collided on'http'). Unregister handles now delete by identity rather than by id.allSettled. A throwing transport becomes anok: falseack instead of rejecting the batch and discarding the acks of transports that succeeded.Privacy
requireRedacted,allowedConsent, andmaxEnvelopeBytesgate every send before any transport runs.requireRedactedmirrors the option in@askable-ui/mcpand defaults tofalsefor the same reason.Previously the envelope copied
packet.privacy.consentand sent unconditionally — and sincetoContextPacket()stampsconsent: 'implicit'andredacted: falseunless sanitizers are registered, that field was decorative on the one component that actually crosses the trust boundary.API
sendAgentRequest()accepts actx.toAgentRequest()payload directly, so apps no longer resolve context twice to reach the bridge. Duck-typed, so this package keeps zero dependency on core.payload.metadataadded to carry the request metadata.isAskableBridgeEnvelope()validatesconsent(the field receivers gate on) and rejects arrays; its localisRecordhad diverged from the one in@askable-ui/context.isAskableBridgeVersionSupported().dispose(); failed HTTP requests report the response body, truncated atmaxErrorBodyChars.Docs
toContextPacketAsync()— the only form that resolves sources registered withctx.registerSource()intosurrounding.sources. Every example used the sync method, so bridge consumers were silently sending thinner packets than the same app exposes over MCP.Also here
chore(examples): consume Askable 0.17.1— examples were pinned^0.17.0against published 0.17.1, failingcheck-example-askable-versionson main and turningstatic / qualityred on every open PR. npm and pnpm lockfiles refreshed; the pnpm lockfile had drifted to 0.16.0.Verification
npm run build --workspaces→ 0npm test→ 0, 1216 passed across 13 workspacesvitepress build→ 0check-example-askable-versions,check-publish-package-coverage,check-mcp-server-manifest→ all OKHeadersInitforms, duplicate ids, partial transport failure, privacy gates, abort/dispose, agent-request interop, and guard rejection cases — each must-fix finding has a test that fails without its fix.Rebased onto main after #405 and #398 merged, then reinstalled and re-verified against vitest 4.1.10 and @types/node 26.