|
24 | 24 | const SANDBOX_RESOURCE_READY_METHOD = |
25 | 25 | "ui/notifications/sandbox-resource-ready"; |
26 | 26 |
|
| 27 | + // Optionally restrict which origins are allowed to send sandbox HTML. |
| 28 | + // Fill this array with explicit origins (for example, ["https://your-app.com"]). |
| 29 | + // Leaving it empty will accept messages from any origin, but HTML is still sanitized. |
| 30 | + const ALLOWED_ORIGINS = []; |
| 31 | + |
| 32 | + function sanitizeHtml(html) { |
| 33 | + if (window.DOMPurify && typeof window.DOMPurify.sanitize === "function") { |
| 34 | + return window.DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: false }); |
| 35 | + } |
| 36 | + |
| 37 | + // Very conservative fallback: strip <script> tags and common inline event handlers. |
| 38 | + const parser = new DOMParser(); |
| 39 | + const doc = parser.parseFromString(html, "text/html"); |
| 40 | + |
| 41 | + // Remove all <script> elements. |
| 42 | + doc.querySelectorAll("script").forEach((el) => el.remove()); |
| 43 | + |
| 44 | + // Remove inline event handlers such as onclick, onload, etc. |
| 45 | + doc.querySelectorAll("*").forEach((el) => { |
| 46 | + [...el.attributes].forEach((attr) => { |
| 47 | + if (/^on/i.test(attr.name)) { |
| 48 | + el.removeAttribute(attr.name); |
| 49 | + } |
| 50 | + }); |
| 51 | + }); |
| 52 | + |
| 53 | + return doc.documentElement.innerHTML; |
| 54 | + } |
| 55 | + |
27 | 56 | // Notify host that we are ready to receive the app resource |
28 | 57 | window.parent.postMessage( |
29 | 58 | { |
|
36 | 65 |
|
37 | 66 | // Listen for the app resource (HTML) from the host |
38 | 67 | window.addEventListener("message", (event) => { |
| 68 | + // If ALLOWED_ORIGINS is non-empty, enforce origin restriction. |
| 69 | + if ( |
| 70 | + Array.isArray(ALLOWED_ORIGINS) && |
| 71 | + ALLOWED_ORIGINS.length > 0 && |
| 72 | + !ALLOWED_ORIGINS.includes(event.origin) |
| 73 | + ) { |
| 74 | + return; |
| 75 | + } |
| 76 | + |
39 | 77 | const message = event.data; |
40 | 78 | if ( |
41 | 79 | message && |
|
47 | 85 | const { html } = message.params; |
48 | 86 | if (html) { |
49 | 87 | // Sanitize the HTML before writing it to the document |
50 | | - const safeHtml = window.DOMPurify |
51 | | - ? window.DOMPurify.sanitize(html) |
52 | | - : html; |
| 88 | + const safeHtml = sanitizeHtml(html); |
53 | 89 | document.open(); |
54 | 90 | document.write(safeHtml); |
55 | 91 | document.close(); |
|
0 commit comments