mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
fix(web): sandbox the speaker-notes presenter deck iframes (#5571)
This commit is contained in:
@@ -244,15 +244,15 @@ export function buildSpeakerNotesPresenterHtml(options: {
|
||||
<button type="button" id="reset"></button>
|
||||
<div class="counter" id="counter"></div>
|
||||
</div>
|
||||
<div class="current"><iframe id="current" title="Current slide"></iframe></div>
|
||||
<div class="current"><iframe id="current" title="Current slide" sandbox="allow-scripts"></iframe></div>
|
||||
<div class="filmstrip">
|
||||
<section id="previous-section">
|
||||
<div class="thumb-label" id="previous-label"></div>
|
||||
<div class="thumb-frame"><iframe id="previous" title="Previous slide"></iframe></div>
|
||||
<div class="thumb-frame"><iframe id="previous" title="Previous slide" sandbox="allow-scripts"></iframe></div>
|
||||
</section>
|
||||
<section id="next-section">
|
||||
<div class="thumb-label" id="next-label"></div>
|
||||
<div class="thumb-frame"><iframe id="next" title="Next slide"></iframe></div>
|
||||
<div class="thumb-frame"><iframe id="next" title="Next slide" sandbox="allow-scripts"></iframe></div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -372,4 +372,36 @@ describe('speaker notes HTML helpers', () => {
|
||||
expect(html).toContain('window.resizeTo(nextWidth, nextHeight)');
|
||||
expect(html).toContain("window.addEventListener('resize', scheduleMinimumWindowSize)");
|
||||
});
|
||||
|
||||
it('sandboxes the presenter slide iframes to an opaque origin', () => {
|
||||
const html = buildSpeakerNotesPresenterHtml({
|
||||
previewHtml: '<section class="slide">One</section>',
|
||||
title: 'Deck',
|
||||
projectId: 'project-1',
|
||||
fileName: 'deck.html',
|
||||
notes: ['Intro'],
|
||||
initialSlideIndex: 0,
|
||||
slideCount: 1,
|
||||
labels: {
|
||||
title: 'Speaker notes',
|
||||
edit: 'Edit',
|
||||
save: 'Save notes',
|
||||
pause: 'Pause',
|
||||
resume: 'Resume',
|
||||
reset: 'Reset',
|
||||
previous: 'Previous',
|
||||
next: 'Next',
|
||||
empty: 'Empty',
|
||||
slide: 'Slide {current} / {total}',
|
||||
},
|
||||
});
|
||||
// The srcdoc loaded into each frame is the full, untrusted deck (scripts
|
||||
// included); the frames must run it in an opaque origin so it cannot reach
|
||||
// the app's storage or daemon.
|
||||
for (const id of ['current', 'previous', 'next']) {
|
||||
const tag = html.match(new RegExp(`<iframe id="${id}"[^>]*>`))?.[0] ?? '';
|
||||
expect(tag).toContain('sandbox="allow-scripts"');
|
||||
expect(tag).not.toContain('allow-same-origin');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user