fix(import): extend cross-origin MessageChannel validation to import frame [INT-783][ENG-4597][ENG-4598] - #130
Open
justinformentin wants to merge 2 commits into
Conversation
… import frame Mirrors the TURNKEY_INIT_MESSAGE_CHANNEL gate added to export-and-sign in PR #129 (#129). The import frame's handler previously only checked event.ports?.[0]; it now also validates: - event.source === window.parent (direct parent only) - event.origin && event.origin !== "null" (concrete, non-opaque origin) - event.ports?.length === 1 (exactly one transferred port) Closes the identical class of vulnerability INT-697 fixed in export-and-sign. Pre-existing gap; not introduced by PR #129. Also adds six Jest tests for the new gate conditions and rebuilds the production bundle (content hash: 45de86a592cd0d80ccd0). Linear: INT-783 https://linear.app/turnkey/issue/INT-783
justinformentin
force-pushed
the
jf/int-783-import-frame-apply-cross-origin-messagechannel-validation
branch
from
August 7, 2026 19:07
207de18 to
f1647ae
Compare
…ing (ENG-4597) Previously, onInjectImportBundle() in the v1.0.0 path would only log a console.warn when organizationId or userId was omitted by the caller, allowing signed import bundles to be accepted without org/user binding. This change converts both warnings into hard errors: - Missing organizationId → throws with message indicating iframe-stamper >= v2.0.0 is required - Missing userId → throws with same guidance The existing equality checks (signedData must match the supplied values) are preserved unchanged. The now-obsolete TODO comments and console.warn calls are removed. Tests: new describe block 'onInjectImportBundle org/user binding (import frame)' in import/index.test.js covers: - missing organizationId (undefined and empty string) - missing userId (undefined and empty string) - mismatched organizationId / userId still throws - valid matching bundle succeeds (BUNDLE_INJECTED) Bundle rebuilt: index.bundle.808edbe601034931b90e.js
justinformentin
force-pushed
the
jf/int-783-import-frame-apply-cross-origin-messagechannel-validation
branch
from
August 10, 2026 15:03
1a7b31a to
e0a04e0
Compare
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.
Summary
Extends the cross-origin
MessageChannelvalidation from INT-697 / PR #129 to the import frame, and closes theorganizationId/userIdbinding gap that allowed legacy callers to skip bundle binding checks.PR #129 hardened the
export-and-signframe'sTURNKEY_INIT_MESSAGE_CHANNELhandler against opaque origins and non-parent senders. Theimportframe had the same pre-existing gap and was not touched by PR #129.Linear: INT-783 https://linear.app/turnkey/issue/INT-783
Security tickets addressed:
ENG-4598 (TKA-20260806-014) https://linear.app/turnkey/issue/ENG-4598 — "The hosted import frame accepts the first
MessageChannelfrom any sender." This PR closes the channel-seizure vector by requiring the sender to be the direct parent with a concrete origin.ENG-4597 - https://linear.app/turnkey/issue/ENG-4597
Fix 1: Cross-origin MessageChannel gate (ENG-4598)
Security ticket: ENG-4598 (TKA-20260806-014) — "The hosted import frame accepts the
first MessageChannel from any sender."
Gate now requires:
event.source === window.parent— only the direct parent frame may establish the channelevent.origin && event.origin !== "null"— opaque/sandboxed origins are rejectedevent.ports?.length === 1— exactly one transferred port requiredFix 2: Import bundle org/user binding (ENG-4597)
Security ticket: ENG-4597 (TKA-20260806-015) — "The hosted import frame accepts signed
import bundles without organization/user binding when legacy callers omit those fields."
onInjectImportBundle()previously logged aconsole.warnand skipped the binding checkwhen
organizationId/userIdwas absent. Both now hard-reject (throw) on missing.Existing mismatch checks unchanged.
Breaking change: iframe-stamper < v2.0.0 (or integrations omitting these fields) now
receive an ERROR response.
Validation
no-consolewarnings (none from this change)45de86a592cd0d80ccd0Reference