From 306e8c421bf7271ad787414084eedf6e4f2ca466 Mon Sep 17 00:00:00 2001 From: Jamie Benstead Date: Fri, 28 Aug 2026 15:42:41 +0100 Subject: [PATCH 1/6] Sanitise project instructions before rendering them Instruction step HTML was assigned to innerHTML unsanitised, so a step could run script in the host page's origin, where the login session is stored. Every step now goes through DOMPurify, covering both the `instructions` attribute and steps loaded with a project. Two tags DOMPurify drops by default are kept because real content needs them: `use`, which draws the icons in a scratchblocks SVG, and `iframe`, which is then restricted to the editor's own origins so the embedded project viewers in project instructions keep working. --- README.md | 12 + .../InstructionsStep/InstructionsStep.jsx | 11 +- .../InstructionsStep.test.jsx | 30 +++ src/utils/sanitiseInstructions.js | 52 +++++ src/utils/sanitiseInstructions.test.js | 210 ++++++++++++++++++ 5 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 src/utils/sanitiseInstructions.js create mode 100644 src/utils/sanitiseInstructions.test.js diff --git a/README.md b/README.md index d5f19eb20..3752b6526 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,18 @@ Styles from the parent application can be passed to the web component in a few d } ``` +#### Instructions Sanitisation + +Instruction steps are rendered into the page with `innerHTML`, so every step is +sanitised with DOMPurify first (see `src/utils/sanitiseInstructions.js`). This +applies to steps passed in the `instructions` attribute and to steps loaded with +a project. Scripts, event handler attributes, `javascript:` and `data:` URLs and +stylesheets outside a scratchblocks SVG are removed. + +`', + "iframe srcdoc": + '', + "allowed origin iframe with srcdoc": + '', + object: '', + embed: '', + "meta refresh": + '', + base: '', + "link stylesheet": + '', + "style element": "", + "style import": "", + "external svg use": + '', + template: "", + noscript: + '