fix(import): extend cross-origin MessageChannel validation to import frame (INT-783) - #130
Open
justinformentin wants to merge 2 commits into
Open
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
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.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 ticket 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.Before (import/src/index.js)
After
What changed
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 required (was: any truthy ports[0])The import frame is intentionally simpler than export-and-sign (no persistent embedded key, no telemetry, no legacy origin binding) — only the gate condition is updated.
Validation
no-consolewarnings (none from this change)45de86a592cd0d80ccd0Reference