|
641 | 641 | const isSameOrigin = event.origin === window.origin; |
642 | 642 | const type = event.data?.type; |
643 | 643 |
|
644 | | - // Prompt-related message types only submit text to the chat input — |
645 | | - // functionally equivalent to the user typing. When same-origin is |
646 | | - // enabled they go through immediately. When it is disabled (opaque |
647 | | - // origin) we show a confirmation dialog so the user stays in control. |
648 | | - const iframePromptTypes = ['input:prompt', 'input:prompt:submit', 'action:submit']; |
| 644 | + // Prompt-driving message types let an embedding page control the chat |
| 645 | + // input / submission. Cross-origin sources are only trusted when the |
| 646 | + // user has explicitly opted in via the "iframe Sandbox Allow Same |
| 647 | + // Origin" interface setting (the same toggle that governs whether |
| 648 | + // rendered iframes receive `allow-same-origin`). |
| 649 | + const promptTypes = ['input:prompt', 'input:prompt:submit', 'action:submit']; |
| 650 | + const isTrusted = isSameOrigin || ($settings?.iframeSandboxAllowSameOrigin ?? false); |
| 651 | +
|
| 652 | + // Non-prompt message types are always restricted to same-origin only. |
| 653 | + if (!isSameOrigin && !promptTypes.includes(type)) { |
| 654 | + return; |
| 655 | + } |
649 | 656 |
|
650 | | - if (!isSameOrigin && !iframePromptTypes.includes(type)) { |
| 657 | + // Prompt types from an untrusted cross-origin source are silently dropped. |
| 658 | + if (promptTypes.includes(type) && !isTrusted) { |
651 | 659 | return; |
652 | 660 | } |
653 | 661 |
|
654 | 662 | if (type === 'action:submit') { |
655 | 663 | console.debug(event.data.text); |
656 | 664 |
|
657 | 665 | if (prompt !== '') { |
658 | | - await tick(); |
659 | | - submitHandler(prompt); |
| 666 | + if (isSameOrigin) { |
| 667 | + await tick(); |
| 668 | + submitHandler(prompt); |
| 669 | + } else { |
| 670 | + eventConfirmationInput = false; |
| 671 | + eventConfirmationTitle = $i18n.t('Confirm Prompt from Embed'); |
| 672 | + eventConfirmationMessage = prompt; |
| 673 | + eventCallback = async (confirmed: boolean) => { |
| 674 | + if (confirmed) { |
| 675 | + await tick(); |
| 676 | + submitHandler(prompt); |
| 677 | + } |
| 678 | + }; |
| 679 | + showEventConfirmation = true; |
| 680 | + } |
660 | 681 | } |
661 | 682 | } |
662 | 683 |
|
|
679 | 700 | await tick(); |
680 | 701 | submitHandler(event.data.text); |
681 | 702 | } else { |
682 | | - // Cross-origin: ask user to confirm before submitting |
683 | 703 | eventConfirmationInput = false; |
684 | 704 | eventConfirmationTitle = $i18n.t('Confirm Prompt from Embed'); |
685 | 705 | eventConfirmationMessage = event.data.text; |
|
0 commit comments