diff --git a/docs/src/guide/client/using-a-proxy.md b/docs/src/guide/client/using-a-proxy.md index 02fef1f4..6ad07794 100644 --- a/docs/src/guide/client/using-a-proxy.md +++ b/docs/src/guide/client/using-a-proxy.md @@ -38,7 +38,7 @@ A valid proxy script must: 2. **Validate the URL**: It must validate that the provided URL is a valid `http:` or `https:` URL to prevent abuse. 3. **Render in an Iframe**: The script should dynamically create an iframe and set its `src` to the validated target URL. 4. **Sandbox the Iframe**: The iframe must be sandboxed to restrict its capabilities. A minimal sandbox policy would be `allow-scripts allow-same-origin`. -5. **Forward `postMessage` Events**: To allow communication between the host application and the embedded external URL, the proxy needs to forward `message` events between `window.parent` and the iframe's `contentWindow`. +5. **Forward `postMessage` Events**: To allow communication between the host application and the embedded external URL, the proxy needs to forward `message` events between `window.parent` and the iframe's `contentWindow`. For security, it's critical to use a specific `targetOrigin` instead of `*` in `postMessage` calls whenever possible. The `targetOrigin` for messages to the iframe should be the external URL's origin; Messages to the parent will resort to `*`. ### Example Self-Hosted Proxy diff --git a/packages/client/scripts/proxy/index.html b/packages/client/scripts/proxy/index.html index 24c72607..5460628d 100644 --- a/packages/client/scripts/proxy/index.html +++ b/packages/client/scripts/proxy/index.html @@ -35,7 +35,7 @@ try { const url = new URL(string); return url.protocol === 'http:' || url.protocol === 'https:'; - } catch (_) { + } catch (error) { return false; } } @@ -50,14 +50,15 @@ inner.style = 'width:100%; height:100%; border:none;'; inner.sandbox = 'allow-same-origin allow-scripts'; document.body.appendChild(inner); + const urlOrigin = new URL(target).origin; + window.addEventListener('message', (event) => { - // listen for messages from the iframe and send them to the parent - if (event.source === inner.contentWindow) { - window.parent.postMessage(event.data, '*'); - } - // listen for messages from the parent and send them to the iframe if (event.source === window.parent) { - inner.contentWindow.postMessage(event.data, '*'); + // listen for messages from the parent and send them to the iframe + inner.contentWindow.postMessage(event.data, urlOrigin); + } else if (event.source === inner.contentWindow) { + // listen for messages from the iframe and send them to the parent + window.parent.postMessage(event.data, '*'); } }); }