Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Cross-Window Messages: Origin, Source, Schema, and Replay

Last updated: 5 Oct 20267 min read
tutorial
IntermediateBy AITrove Editorial

Window messaging crosses a document boundary by sending structured data to a Window reference. A sender chooses a target origin; a receiver checks the message origin and, when it has one, the expected source window. Neither check validates the message body or grants permission for the requested operation. Model messages as versioned commands with a small allowlist, size limit, and correlation ID. A message is an input from another execution context, even when both teams work on the same product.

Working case

The supplier viewer posts that attachment reference 47 was selected. The host expects a message from the viewer's exact origin and the current iframe window. It also expects protocol version 3, a selection command, the active request ID, and an attachment ID in the case's allowed set. A different tab can send a message to the host, and the viewer can be replaced by a later navigation. Neither message should update the report. The host does not echo private report text back merely because a frame asks for it.

Implementation boundary

javascript
function acceptViewerMessage(event, expectedSource, pendingRequest) {
  const message = event.data;
  return event.origin === 'https://viewer.inspection.test' && event.source === expectedSource &&
    message?.version === 3 && message?.type === 'attachment-selected' &&
    message?.requestId === pendingRequest && Number.isInteger(message?.attachmentId);
}
const viewerWindow = {};
console.log(acceptViewerMessage({ origin: 'https://viewer.inspection.test', source: viewerWindow, data: { version: 3, type: 'attachment-selected', requestId: 'r47', attachmentId: 62 } }, viewerWindow, 'r47'));
// Output: true

When sending, specify the exact recipient origin. This contract assumes the distinct-origin frame retains its real origin; an opaque sandbox origin appears as null and cannot be checked against a unique sender origin. On receipt, compare event.origin with the configured origin string without adding a path or trailing slash, and compare event.source with the current frame reference. Validate a plain-data schema before reading nested fields. A request ID ties a response to the active selection; retire IDs after use so a late message cannot repeat the action. Recheck authorization for the attachment on the host server before changing durable state. If the frame navigates, invalidate outstanding requests and establish a fresh handshake. Never turn message text into HTML or script. Log a reason category for rejected messages without storing payloads.

Cost and boundaries

A fixed-size message and map lookup are O(1) for a bounded schema. Validating a large object or recursively cloning it can consume memory and block the main thread, so limit depth and bytes at the protocol boundary. Keeping pending requests forever leaks timers and closures; expire them. Versioning adds a little coordination work, but it lets host and viewer roll out at different times without silently treating unknown fields as authority. Measure rejection rates during rollout without recording the sensitive attachment ID in analytics.

Failure trace

The host checks only the payload type. A promotional frame sends the same command shape and selects an unrelated attachment. A second build checks origin but accepts a response for an old request after the reviewer has switched cases. Reproduce both cases, then attempt an object with an unexpected array, a very long string, and a missing protocol version. Each should be ignored. Also test the intended viewer after it reloads and after the host changes cases; the valid path must reestablish a fresh request instead of reusing old state.

Verification

  • Wrong origin and wrong source are each rejected.
  • Stale request IDs cannot repeat a selection.
  • Server authorization still decides durable changes.

Practice drill

Generate two frame references in a test rig. Send the same selection payload from each and show that only the expected source can pass. Change the active request ID and replay the earlier response. Reject an attachment ID absent from the current case's allowlist. Then deploy a version-4 viewer against a version-3 host and confirm the host reports an unsupported protocol state with a manual selection fallback.

Decision note

The receiver validates origin, source, shape, correlation, and server authority as separate gates.

Common Mistakes

  • Using a wildcard target origin for private messages.
  • Treating a matching origin as a valid schema.
  • Keeping a request ID active after case change.

Connected lessons

Build Project: embedded attachment viewer contract and review Web Development: embedded interfaces and build integrity quiz; follow Embedded Interfaces and Cross-Window Contracts; Frame Sandbox, Capabilities, and Fallback; MessageChannel Lifetime and Request Correlation; Popup Handoff, Return, and Window Ownership; Embedding and Browser Capability Headers; Object-Level Authorization for Reads and Writes.

Further connections

Extension Message Contracts and Page Data Boundary.

web-tech
web-development
Storage details