@dynamic-labs/iframe-setup 5.0.0-rc.0 → 5.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +72 -1
- package/README.md +57 -2
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +2 -2
- package/src/lib/setupIframe/setupIframe.cjs +45 -2
- package/src/lib/setupIframe/setupIframe.js +45 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,76 @@
|
|
|
1
1
|
|
|
2
|
-
## [5.0.0-rc.
|
|
2
|
+
## [5.0.0-rc.1](https://github.com/dynamic-labs/dynamic-auth/compare/v5.0.0-rc.0...v5.0.0-rc.1) (2026-07-17)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### ⚠ BREAKING CHANGES
|
|
6
|
+
|
|
7
|
+
* move legacy embedded wallet to waas upgrade flow to new legacy-embedded-wallet-migration package (#11841)
|
|
8
|
+
* drop default injection of legacy embedded wallet connectors (#11833)
|
|
9
|
+
* remove legacy embedded wallet support (#11979)
|
|
10
|
+
* throw when legacy embedded wallet is detected without migration provider (#11855)
|
|
11
|
+
* remove deprecated eclipse package (#11831)
|
|
12
|
+
* remove deprecated functions and props (#11832)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### [4.92.4](https://github.com/dynamic-labs/dynamic-auth/compare/v4.92.3...v4.92.4) (2026-07-16)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **bitcoin:** per-network address switching and dust-limit send validation [v4] ([#11970](https://github.com/dynamic-labs/dynamic-auth/issues/11970)) ([76a4a9a](https://github.com/dynamic-labs/dynamic-auth/commit/76a4a9a5025d78798ebd1beffe6c0af59d2d029a)), closes [#11896](https://github.com/dynamic-labs/dynamic-auth/issues/11896) [#11800](https://github.com/dynamic-labs/dynamic-auth/issues/11800)
|
|
21
|
+
* **midnight:** per-network addresses in deposit and wallet info views [v4] ([#11949](https://github.com/dynamic-labs/dynamic-auth/issues/11949)) ([978446a](https://github.com/dynamic-labs/dynamic-auth/commit/978446aca8546eb038ba9ed3be0503d10594ee15))
|
|
22
|
+
* **midnight:** resolve wallet address per selected network [v4] ([#11948](https://github.com/dynamic-labs/dynamic-auth/issues/11948)) ([d6f858c](https://github.com/dynamic-labs/dynamic-auth/commit/d6f858c5e35defda7ed73cf97b3fdbe5ed9d131d))
|
|
23
|
+
* set useMetamaskSdk to true by default ([#11926](https://github.com/dynamic-labs/dynamic-auth/issues/11926)) ([75b5a4a](https://github.com/dynamic-labs/dynamic-auth/commit/75b5a4a0fe8b1a375afce145c0b8bdc3ce761117))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Bug Fixes
|
|
27
|
+
|
|
28
|
+
* **midnight:** align per-network code with the final main iteration [v4] ([#11971](https://github.com/dynamic-labs/dynamic-auth/issues/11971)) ([3ef3ba8](https://github.com/dynamic-labs/dynamic-auth/commit/3ef3ba8c090dfd9e4286b4e51bf350ea5e6feac7))
|
|
29
|
+
* settle social sign-in when captcha is backed out or oauth popup never responds (v4) ([#11956](https://github.com/dynamic-labs/dynamic-auth/issues/11956)) ([ad49477](https://github.com/dynamic-labs/dynamic-auth/commit/ad49477f2acf61a154bb79cbe26b24f803cdb0e2))
|
|
30
|
+
* validate that private key is not empty before upgrading to WaaS ([#11952](https://github.com/dynamic-labs/dynamic-auth/issues/11952)) ([21dfb83](https://github.com/dynamic-labs/dynamic-auth/commit/21dfb83cb29e42b335bc94a0cdd2062cf14a262a))
|
|
31
|
+
|
|
32
|
+
### [4.92.3](https://github.com/dynamic-labs/dynamic-auth/compare/v4.92.2...v4.92.3) (2026-07-10)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### Bug Fixes
|
|
36
|
+
|
|
37
|
+
* **sdk-react-core:** fix deterministic 'Wallet not found' crash in embedded wallet export (v4) ([#11906](https://github.com/dynamic-labs/dynamic-auth/issues/11906)) ([913ef23](https://github.com/dynamic-labs/dynamic-auth/commit/913ef236b26245488e1cd5db7e874601b65ff0a2)), closes [#11905](https://github.com/dynamic-labs/dynamic-auth/issues/11905) [#11729](https://github.com/dynamic-labs/dynamic-auth/issues/11729)
|
|
38
|
+
|
|
39
|
+
### [4.92.2](https://github.com/dynamic-labs/dynamic-auth/compare/v4.92.1...v4.92.2) (2026-07-09)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Bug Fixes
|
|
43
|
+
|
|
44
|
+
* engage captcha during step-up OTP re-auth ([#11879](https://github.com/dynamic-labs/dynamic-auth/issues/11879)) ([585460a](https://github.com/dynamic-labs/dynamic-auth/commit/585460a8976803a8ed0aad16a4a00047bd6c115a))
|
|
45
|
+
* **waas:** gate v1 wallet upgrade on recovery for email-only wallets ([#11897](https://github.com/dynamic-labs/dynamic-auth/issues/11897)) ([5a6f0c6](https://github.com/dynamic-labs/dynamic-auth/commit/5a6f0c6bf3120e59cf502004d09fae56f193e977))
|
|
46
|
+
|
|
47
|
+
### [4.92.1](https://github.com/dynamic-labs/dynamic-auth/compare/v4.92.0...v4.92.1) (2026-07-09)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
### Bug Fixes
|
|
51
|
+
|
|
52
|
+
* **ethereum:** fire in-app-browser redirect on sign for injected EVM wallets that use in-app-browser experience ([#11888](https://github.com/dynamic-labs/dynamic-auth/issues/11888)) ([5116d91](https://github.com/dynamic-labs/dynamic-auth/commit/5116d91ab2c71000a490d72c5d278549d4d8ae9a))
|
|
53
|
+
* **sdk-react-core:** show clear message for Phantom redirect signing failures (v4 backport) ([#11886](https://github.com/dynamic-labs/dynamic-auth/issues/11886)) ([60ac897](https://github.com/dynamic-labs/dynamic-auth/commit/60ac897ba81f7758ccd7a05f97b619785e1f50a7))
|
|
54
|
+
* **social:** use redirect strategy for step-up OAuth on mobile [V4 backport] ([#11881](https://github.com/dynamic-labs/dynamic-auth/issues/11881)) ([42a202e](https://github.com/dynamic-labs/dynamic-auth/commit/42a202e6255de8db73df02eff37c0b10b24fef1a))
|
|
55
|
+
* **solana:** fire in-app-browser redirect on sign and wallet switch ([#11871](https://github.com/dynamic-labs/dynamic-auth/issues/11871)) ([4e2d6b7](https://github.com/dynamic-labs/dynamic-auth/commit/4e2d6b7ac8fdef5bf7c62b8a726ecaef1c6210ec))
|
|
56
|
+
* **solana:** resolve Phantom/Backpack provider collision and Backpack >=0.10.x connect hangs ([#11856](https://github.com/dynamic-labs/dynamic-auth/issues/11856)) ([#11882](https://github.com/dynamic-labs/dynamic-auth/issues/11882)) ([5784aff](https://github.com/dynamic-labs/dynamic-auth/commit/5784aff9641bbc85445fb466f3ab1d6a14331e73))
|
|
57
|
+
|
|
58
|
+
## [4.92.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.6...v4.92.0) (2026-07-08)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
### Features
|
|
62
|
+
|
|
63
|
+
* **captcha:** add Cloudflare Turnstile provider support alongside hCaptcha (v4) ([#11798](https://github.com/dynamic-labs/dynamic-auth/issues/11798)) ([114c770](https://github.com/dynamic-labs/dynamic-auth/commit/114c7702e900d8dedeebe7be867de35d11a93f31))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
### Bug Fixes
|
|
67
|
+
|
|
68
|
+
* **ethereum-aa:** resolve kernel client config per wallet (v4) ([#11870](https://github.com/dynamic-labs/dynamic-auth/issues/11870)) ([1b66d79](https://github.com/dynamic-labs/dynamic-auth/commit/1b66d79b4a32b4b6de433b7536bc46e6719224c6))
|
|
69
|
+
* **iframe-setup:** block dangerous URL schemes and verify sender in OPEN_URL ([#11819](https://github.com/dynamic-labs/dynamic-auth/issues/11819)) ([329b27e](https://github.com/dynamic-labs/dynamic-auth/commit/329b27e9fac825916ab227ec8cf93dc343898923))
|
|
70
|
+
* improve social OAuth error messages ([#11837](https://github.com/dynamic-labs/dynamic-auth/issues/11837)) ([8e57c06](https://github.com/dynamic-labs/dynamic-auth/commit/8e57c067c5a89111a32a12fb82e190cf6c46ad67))
|
|
71
|
+
* **react-native-extension:** reject path traversal in downloadFile fileName ([#11816](https://github.com/dynamic-labs/dynamic-auth/issues/11816)) ([9367a56](https://github.com/dynamic-labs/dynamic-auth/commit/9367a56b6daa853d7f7e7f5534261bc68825b239))
|
|
72
|
+
* **sdk-react-core:** display exactly the bytes signed in personal_sign preview ([#11818](https://github.com/dynamic-labs/dynamic-auth/issues/11818)) ([30b9382](https://github.com/dynamic-labs/dynamic-auth/commit/30b93829122f00060cb484aef09a03294c03f651))
|
|
73
|
+
|
|
3
74
|
|
|
4
75
|
### [4.91.6](https://github.com/dynamic-labs/dynamic-auth/compare/v4.91.5...v4.91.6) (2026-07-03)
|
|
5
76
|
|
package/README.md
CHANGED
|
@@ -146,12 +146,20 @@ export const setupIframe = (
|
|
|
146
146
|
): VoidFunction => {
|
|
147
147
|
if (typeof window === 'undefined') return () => {};
|
|
148
148
|
|
|
149
|
-
const messageHandler = createMessageHandler<IFRAME_EVENTS>(
|
|
149
|
+
const messageHandler = createMessageHandler<IFRAME_EVENTS>(
|
|
150
|
+
window,
|
|
151
|
+
origin,
|
|
152
|
+
iframe,
|
|
153
|
+
);
|
|
150
154
|
const messageSender = createMessageSender<IFRAME_EVENTS>(iframe);
|
|
151
155
|
|
|
152
156
|
// Add event listener to handle deeplink
|
|
153
157
|
const setupOpenUrlHandler = () =>
|
|
154
158
|
messageHandler('OPEN_URL', ({ url, target = 'self', features }) => {
|
|
159
|
+
// This navigates the host top window, so never honor a URL whose scheme
|
|
160
|
+
// can execute script in the host origin (iframe->host XSS).
|
|
161
|
+
if (hasDangerousScheme(url)) return;
|
|
162
|
+
|
|
155
163
|
if (target === 'blank') {
|
|
156
164
|
window.open(url, '_blank', features);
|
|
157
165
|
} else {
|
|
@@ -220,6 +228,45 @@ export const setupIframe = (
|
|
|
220
228
|
|
|
221
229
|
// Utils
|
|
222
230
|
|
|
231
|
+
/**
|
|
232
|
+
* URL schemes that can execute script in the host origin. Navigating the host
|
|
233
|
+
* top window to any of these turns an OPEN_URL message into arbitrary code
|
|
234
|
+
* execution in the integrator's origin, so they are blocked.
|
|
235
|
+
*
|
|
236
|
+
* A deny-list (rather than an http/https allow-list) is used deliberately:
|
|
237
|
+
* wallet flows legitimately open custom-scheme deep links, and allow-listing
|
|
238
|
+
* http(s) would break them.
|
|
239
|
+
*/
|
|
240
|
+
const DANGEROUS_SCHEMES = [
|
|
241
|
+
'javascript:',
|
|
242
|
+
'data:',
|
|
243
|
+
'blob:',
|
|
244
|
+
'vbscript:',
|
|
245
|
+
'file:',
|
|
246
|
+
];
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Leading characters the browser ignores when resolving a URL scheme: spaces,
|
|
250
|
+
* tabs, newlines and other C0 control chars (U+0000–U+0020). Stripping them
|
|
251
|
+
* defeats obfuscation such as "\tjavascript:alert(1)".
|
|
252
|
+
*/
|
|
253
|
+
// eslint-disable-next-line no-control-regex
|
|
254
|
+
const LEADING_IGNORED_CHARS = /^[\u0000-\u0020]+/;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Returns true when the URL begins with a script-executing scheme.
|
|
258
|
+
*
|
|
259
|
+
* Non-string input is treated as dangerous, leading ignored chars are stripped
|
|
260
|
+
* first, and the comparison is case-insensitive ("JavaScript:" is blocked).
|
|
261
|
+
*/
|
|
262
|
+
const hasDangerousScheme = (url: unknown): boolean => {
|
|
263
|
+
if (typeof url !== 'string') return true;
|
|
264
|
+
|
|
265
|
+
const normalized = url.replace(LEADING_IGNORED_CHARS, '').toLowerCase();
|
|
266
|
+
|
|
267
|
+
return DANGEROUS_SCHEMES.some((scheme) => normalized.startsWith(scheme));
|
|
268
|
+
};
|
|
269
|
+
|
|
223
270
|
/**
|
|
224
271
|
* Custom event dispatched when the parent URL changes via the History API.
|
|
225
272
|
* Used instead of re-patching history per setupIframe call so that multiple
|
|
@@ -262,7 +309,11 @@ const patchHistoryOnce = (): void => {
|
|
|
262
309
|
* Create a message handler for the iframe
|
|
263
310
|
*/
|
|
264
311
|
const createMessageHandler =
|
|
265
|
-
<T extends Record<string, MESSAGE_HANDLER>>(
|
|
312
|
+
<T extends Record<string, MESSAGE_HANDLER>>(
|
|
313
|
+
window: Window,
|
|
314
|
+
origin: string,
|
|
315
|
+
iframe: HTMLIFrameElement,
|
|
316
|
+
) =>
|
|
266
317
|
<EVENT_NAME extends Extract<keyof T, string>>(
|
|
267
318
|
eventName: EVENT_NAME,
|
|
268
319
|
handler: T[EVENT_NAME],
|
|
@@ -270,6 +321,10 @@ const createMessageHandler =
|
|
|
270
321
|
const messageHandler = (event: MessageEvent) => {
|
|
271
322
|
if (event.origin !== origin) return;
|
|
272
323
|
|
|
324
|
+
// Only trust messages coming from this iframe's own window. Checking the
|
|
325
|
+
// origin alone lets any frame/tab at the SDK-iframe origin forge events.
|
|
326
|
+
if (event.source !== iframe.contentWindow) return;
|
|
327
|
+
|
|
273
328
|
const { eventName: incomingEventName, args } = event.data;
|
|
274
329
|
|
|
275
330
|
if (eventName === incomingEventName) {
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/iframe-setup",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.1",
|
|
4
4
|
"description": "Collection of utilities to use the Dynamic SDK in an iframe",
|
|
5
5
|
"author": "Dynamic Labs, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"homepage": "https://www.dynamic.xyz/",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@dynamic-labs/assert-package-version": "5.0.0-rc.
|
|
21
|
+
"@dynamic-labs/assert-package-version": "5.0.0-rc.1"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {}
|
|
24
24
|
}
|
|
@@ -22,10 +22,14 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
22
22
|
const setupIframe = (iframe, origin) => {
|
|
23
23
|
if (typeof window === 'undefined')
|
|
24
24
|
return () => { };
|
|
25
|
-
const messageHandler = createMessageHandler(window, origin);
|
|
25
|
+
const messageHandler = createMessageHandler(window, origin, iframe);
|
|
26
26
|
const messageSender = createMessageSender(iframe);
|
|
27
27
|
// Add event listener to handle deeplink
|
|
28
28
|
const setupOpenUrlHandler = () => messageHandler('OPEN_URL', ({ url, target = 'self', features }) => {
|
|
29
|
+
// This navigates the host top window, so never honor a URL whose scheme
|
|
30
|
+
// can execute script in the host origin (iframe->host XSS).
|
|
31
|
+
if (hasDangerousScheme(url))
|
|
32
|
+
return;
|
|
29
33
|
if (target === 'blank') {
|
|
30
34
|
window.open(url, '_blank', features);
|
|
31
35
|
}
|
|
@@ -82,6 +86,41 @@ const setupIframe = (iframe, origin) => {
|
|
|
82
86
|
return () => cleanupHandlers.forEach((offHandler) => offHandler());
|
|
83
87
|
};
|
|
84
88
|
// Utils
|
|
89
|
+
/**
|
|
90
|
+
* URL schemes that can execute script in the host origin. Navigating the host
|
|
91
|
+
* top window to any of these turns an OPEN_URL message into arbitrary code
|
|
92
|
+
* execution in the integrator's origin, so they are blocked.
|
|
93
|
+
*
|
|
94
|
+
* A deny-list (rather than an http/https allow-list) is used deliberately:
|
|
95
|
+
* wallet flows legitimately open custom-scheme deep links, and allow-listing
|
|
96
|
+
* http(s) would break them.
|
|
97
|
+
*/
|
|
98
|
+
const DANGEROUS_SCHEMES = [
|
|
99
|
+
'javascript:',
|
|
100
|
+
'data:',
|
|
101
|
+
'blob:',
|
|
102
|
+
'vbscript:',
|
|
103
|
+
'file:',
|
|
104
|
+
];
|
|
105
|
+
/**
|
|
106
|
+
* Leading characters the browser ignores when resolving a URL scheme: spaces,
|
|
107
|
+
* tabs, newlines and other C0 control chars (U+0000–U+0020). Stripping them
|
|
108
|
+
* defeats obfuscation such as "\tjavascript:alert(1)".
|
|
109
|
+
*/
|
|
110
|
+
// eslint-disable-next-line no-control-regex
|
|
111
|
+
const LEADING_IGNORED_CHARS = /^[\u0000-\u0020]+/;
|
|
112
|
+
/**
|
|
113
|
+
* Returns true when the URL begins with a script-executing scheme.
|
|
114
|
+
*
|
|
115
|
+
* Non-string input is treated as dangerous, leading ignored chars are stripped
|
|
116
|
+
* first, and the comparison is case-insensitive ("JavaScript:" is blocked).
|
|
117
|
+
*/
|
|
118
|
+
const hasDangerousScheme = (url) => {
|
|
119
|
+
if (typeof url !== 'string')
|
|
120
|
+
return true;
|
|
121
|
+
const normalized = url.replace(LEADING_IGNORED_CHARS, '').toLowerCase();
|
|
122
|
+
return DANGEROUS_SCHEMES.some((scheme) => normalized.startsWith(scheme));
|
|
123
|
+
};
|
|
85
124
|
/**
|
|
86
125
|
* Custom event dispatched when the parent URL changes via the History API.
|
|
87
126
|
* Used instead of re-patching history per setupIframe call so that multiple
|
|
@@ -117,10 +156,14 @@ const patchHistoryOnce = () => {
|
|
|
117
156
|
/**
|
|
118
157
|
* Create a message handler for the iframe
|
|
119
158
|
*/
|
|
120
|
-
const createMessageHandler = (window, origin) => (eventName, handler) => {
|
|
159
|
+
const createMessageHandler = (window, origin, iframe) => (eventName, handler) => {
|
|
121
160
|
const messageHandler = (event) => {
|
|
122
161
|
if (event.origin !== origin)
|
|
123
162
|
return;
|
|
163
|
+
// Only trust messages coming from this iframe's own window. Checking the
|
|
164
|
+
// origin alone lets any frame/tab at the SDK-iframe origin forge events.
|
|
165
|
+
if (event.source !== iframe.contentWindow)
|
|
166
|
+
return;
|
|
124
167
|
const { eventName: incomingEventName, args } = event.data;
|
|
125
168
|
if (eventName === incomingEventName) {
|
|
126
169
|
handler(...args);
|
|
@@ -18,10 +18,14 @@
|
|
|
18
18
|
const setupIframe = (iframe, origin) => {
|
|
19
19
|
if (typeof window === 'undefined')
|
|
20
20
|
return () => { };
|
|
21
|
-
const messageHandler = createMessageHandler(window, origin);
|
|
21
|
+
const messageHandler = createMessageHandler(window, origin, iframe);
|
|
22
22
|
const messageSender = createMessageSender(iframe);
|
|
23
23
|
// Add event listener to handle deeplink
|
|
24
24
|
const setupOpenUrlHandler = () => messageHandler('OPEN_URL', ({ url, target = 'self', features }) => {
|
|
25
|
+
// This navigates the host top window, so never honor a URL whose scheme
|
|
26
|
+
// can execute script in the host origin (iframe->host XSS).
|
|
27
|
+
if (hasDangerousScheme(url))
|
|
28
|
+
return;
|
|
25
29
|
if (target === 'blank') {
|
|
26
30
|
window.open(url, '_blank', features);
|
|
27
31
|
}
|
|
@@ -78,6 +82,41 @@ const setupIframe = (iframe, origin) => {
|
|
|
78
82
|
return () => cleanupHandlers.forEach((offHandler) => offHandler());
|
|
79
83
|
};
|
|
80
84
|
// Utils
|
|
85
|
+
/**
|
|
86
|
+
* URL schemes that can execute script in the host origin. Navigating the host
|
|
87
|
+
* top window to any of these turns an OPEN_URL message into arbitrary code
|
|
88
|
+
* execution in the integrator's origin, so they are blocked.
|
|
89
|
+
*
|
|
90
|
+
* A deny-list (rather than an http/https allow-list) is used deliberately:
|
|
91
|
+
* wallet flows legitimately open custom-scheme deep links, and allow-listing
|
|
92
|
+
* http(s) would break them.
|
|
93
|
+
*/
|
|
94
|
+
const DANGEROUS_SCHEMES = [
|
|
95
|
+
'javascript:',
|
|
96
|
+
'data:',
|
|
97
|
+
'blob:',
|
|
98
|
+
'vbscript:',
|
|
99
|
+
'file:',
|
|
100
|
+
];
|
|
101
|
+
/**
|
|
102
|
+
* Leading characters the browser ignores when resolving a URL scheme: spaces,
|
|
103
|
+
* tabs, newlines and other C0 control chars (U+0000–U+0020). Stripping them
|
|
104
|
+
* defeats obfuscation such as "\tjavascript:alert(1)".
|
|
105
|
+
*/
|
|
106
|
+
// eslint-disable-next-line no-control-regex
|
|
107
|
+
const LEADING_IGNORED_CHARS = /^[\u0000-\u0020]+/;
|
|
108
|
+
/**
|
|
109
|
+
* Returns true when the URL begins with a script-executing scheme.
|
|
110
|
+
*
|
|
111
|
+
* Non-string input is treated as dangerous, leading ignored chars are stripped
|
|
112
|
+
* first, and the comparison is case-insensitive ("JavaScript:" is blocked).
|
|
113
|
+
*/
|
|
114
|
+
const hasDangerousScheme = (url) => {
|
|
115
|
+
if (typeof url !== 'string')
|
|
116
|
+
return true;
|
|
117
|
+
const normalized = url.replace(LEADING_IGNORED_CHARS, '').toLowerCase();
|
|
118
|
+
return DANGEROUS_SCHEMES.some((scheme) => normalized.startsWith(scheme));
|
|
119
|
+
};
|
|
81
120
|
/**
|
|
82
121
|
* Custom event dispatched when the parent URL changes via the History API.
|
|
83
122
|
* Used instead of re-patching history per setupIframe call so that multiple
|
|
@@ -113,10 +152,14 @@ const patchHistoryOnce = () => {
|
|
|
113
152
|
/**
|
|
114
153
|
* Create a message handler for the iframe
|
|
115
154
|
*/
|
|
116
|
-
const createMessageHandler = (window, origin) => (eventName, handler) => {
|
|
155
|
+
const createMessageHandler = (window, origin, iframe) => (eventName, handler) => {
|
|
117
156
|
const messageHandler = (event) => {
|
|
118
157
|
if (event.origin !== origin)
|
|
119
158
|
return;
|
|
159
|
+
// Only trust messages coming from this iframe's own window. Checking the
|
|
160
|
+
// origin alone lets any frame/tab at the SDK-iframe origin forge events.
|
|
161
|
+
if (event.source !== iframe.contentWindow)
|
|
162
|
+
return;
|
|
120
163
|
const { eventName: incomingEventName, args } = event.data;
|
|
121
164
|
if (eventName === incomingEventName) {
|
|
122
165
|
handler(...args);
|