Skip to content

Commit 7b742b5

Browse files
feat: remove allow-same-origin for better security. (#69)
1 parent 72c5ed4 commit 7b742b5

7 files changed

Lines changed: 795 additions & 313 deletions

File tree

playwright/rendering-modes.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,38 @@ test('editing-transient missing reference runtime errors are suppressed', async
326326
await expect(page.getByRole('status', { name: 'App status' })).not.toHaveText('Error')
327327
})
328328

329+
test('preview iframe sandbox isolates parent origin access', async ({ page }) => {
330+
await waitForInitialRender(page)
331+
332+
const iframe = page.locator('#preview-host iframe')
333+
const sandbox = await iframe.getAttribute('sandbox')
334+
335+
expect(typeof sandbox).toBe('string')
336+
expect(sandbox?.includes('allow-same-origin')).toBeFalsy()
337+
338+
await setComponentEditorSource(
339+
page,
340+
[
341+
'const canReadParentStorage = (() => {',
342+
' try {',
343+
' return Boolean(window.parent.localStorage)',
344+
' } catch {',
345+
' return false',
346+
' }',
347+
'})()',
348+
'',
349+
'export const App = () => (',
350+
" <button type='button'>",
351+
" {canReadParentStorage ? 'parent-readable' : 'parent-blocked'}",
352+
' </button>',
353+
')',
354+
].join('\n'),
355+
)
356+
357+
await expect(page.getByRole('status', { name: 'App status' })).toHaveText('Rendered')
358+
await expect(getPreviewFrame(page).getByRole('button')).toContainText('parent-blocked')
359+
})
360+
329361
test('post-render runtime exceptions from iframe are reported in preview panel', async ({
330362
page,
331363
}) => {

src/app.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,14 @@ const showAppToast = message => {
226226
const previewBackground = createPreviewBackgroundController({
227227
previewBgColorInput,
228228
getPreviewHost: () => previewHost,
229+
onBackgroundColorChange: color => {
230+
if (
231+
renderRuntime &&
232+
typeof renderRuntime.updatePreviewBackgroundColor === 'function'
233+
) {
234+
renderRuntime.updatePreviewBackgroundColor(color)
235+
}
236+
},
229237
getDefaultPreviewBackgroundColor: () => {
230238
if (document.documentElement.dataset.theme === 'light') {
231239
return '#ffffff'

src/modules/preview-background.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const createPreviewBackgroundController = ({
3939
previewBgColorInput,
4040
getPreviewHost,
4141
getDefaultPreviewBackgroundColor,
42+
onBackgroundColorChange,
4243
}) => {
4344
let previewBackgroundColor = null
4445
let previewBackgroundCustomized = false
@@ -66,26 +67,21 @@ export const createPreviewBackgroundController = ({
6667
return
6768
}
6869

69-
const iframe = previewHost.querySelector('iframe')
70-
const iframeDocument = iframe?.contentDocument ?? null
71-
7270
if (typeof color === 'string' && color.length > 0) {
7371
previewHost.style.backgroundColor = color
7472
previewHost.style.setProperty('--preview-iframe-background-color', color)
7573

76-
if (iframeDocument) {
77-
iframeDocument.documentElement.style.backgroundColor = color
78-
iframeDocument.body.style.backgroundColor = color
74+
if (typeof onBackgroundColorChange === 'function') {
75+
onBackgroundColorChange(color)
7976
}
8077
return
8178
}
8279

8380
previewHost.style.removeProperty('background-color')
8481
previewHost.style.removeProperty('--preview-iframe-background-color')
8582

86-
if (iframeDocument) {
87-
iframeDocument.documentElement.style.removeProperty('background-color')
88-
iframeDocument.body.style.removeProperty('background-color')
83+
if (typeof onBackgroundColorChange === 'function') {
84+
onBackgroundColorChange('')
8985
}
9086
}
9187

0 commit comments

Comments
 (0)