diff --git a/CHANGELOG.md b/CHANGELOG.md index c9af701cc..efbc8f28e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Font-family variables that can be used to customise the sans-serif and monospace fonts used in the editor (#1264) - Material symbols font to web component preview page since the Design System depends on this (#1261) - Ability for plugins to add buttons to the SidebarPanel header (#1270, #1271, #1274) +- Prevent access to the session from within the editor (#1275) ### Changed diff --git a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.jsx b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.jsx index ae8a47720..e9febce3f 100644 --- a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.jsx +++ b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.jsx @@ -306,55 +306,86 @@ function HtmlRunner() { if (!externalLink) { const indexPage = parse(focussedComponent(previewFile).content); const body = indexPage.querySelector("body") || indexPage; + const htmlRoot = indexPage.querySelector("html") ?? indexPage; - // insert script to disable access to specific localStorage keys - // localstorage.getItem() is a potential security risk when executing untrusted code const disableLocalStorageScript = ` - + `; + + const disableSessionStorageScript = ` + - `; - - body.insertAdjacentHTML("afterbegin", disableLocalStorageScript); + }; + const apply = (host) => { + if (!host) return; + try { + Object.defineProperty(host, "sessionStorage", { + configurable: false, + enumerable: false, + get: () => stub, + set: () => undefined, + }); + } catch (_) {} + }; + [window, window.parent, window.top, document.defaultView].forEach(apply); + })(); + + `; + + // insert scripts to disable access to specific localStorage keys and sessionStorage + // entirely, they are both potential security risks when executing untrusted code + htmlRoot.insertAdjacentHTML("afterbegin", disableLocalStorageScript); + htmlRoot.insertAdjacentHTML("afterbegin", disableSessionStorageScript); replaceHrefNodes(indexPage, projectCode); replaceSrcNodes(indexPage, projectMedia, projectCode); diff --git a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.js b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.js index 40ad19de9..e797c6cf7 100644 --- a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.js +++ b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.js @@ -289,19 +289,35 @@ describe("When run is triggered", () => { const [generatedHtml] = Blob.mock.calls[0][0]; expect(generatedHtml).toContain(""); + }); + test("Includes localSession disabling script to prevent all access to the session object", () => { + const [generatedHtml] = Blob.mock.calls[0][0]; + + expect(generatedHtml).toContain(""); }); });