Skip to content

fix(playground): guard runner against markup break-out#435

Draft
caugner wants to merge 2 commits into
mainfrom
1440-playground-runner-breakout-guard
Draft

fix(playground): guard runner against markup break-out#435
caugner wants to merge 2 commits into
mainfrom
1440-playground-runner-breakout-guard

Conversation

@caugner

@caugner caugner commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

(⚠️ Mirrored from mdn/fred#1705. ⚠️ )

Description

Update the mirrored Playground runner (cloud-function/src/internal/play/index.js) to guard the generated runner HTML against two markup break-out issues:

  • Warn when malformed HTML swallows the JS <script>: add id="mdn-play-js" to the JS script element and check, in the following ready script, that it is still an HTMLScriptElement. An unclosed or malformed tag in the HTML input (for example <o) is parsed so the following <script> becomes attributes of the open tag, and the user's JS renders as visible text instead of running.
  • Prevent CSS and JS from breaking out of their elements: escape literal </style and </script sequences by inserting a backslash (<\/style, <\/script) before interpolating css and js. The backslash stops the HTML parser from ending the element while remaining equivalent inside CSS/JS strings, where \/ resolves to /.

Motivation

Mirror mdn/fred#1705 into this repo's diverged copy of libs/play/index.js. This file is the deployed source that serves the Playground runner HTML in review and production environments, so this change is required for the fred fix to take effect there.

Additional details

Verified with parse5: rendering { html: "annn <o jwj", ... } yields an element carrying id="mdn-play-js" with tagName o (warning case), normal HTML yields a real <script>, and break-out payloads in css (.a{content:"</style><script>alert(1)</script>"}) and js (console.log("</script><img src=x onerror=alert(1)>")) inject zero <script>/<img> elements into the parsed tree.

Related issues and pull requests

fix for mdn/fred#1440). Required for that fix to take effect in deployed/review environments.

@caugner caugner changed the title fix(play): guard the Playground runner against markup break-out fix(playground): guard runner against markup break-out Jul 17, 2026
caugner added 2 commits July 17, 2026 16:45
An unclosed or malformed tag in the HTML input (for example `<o`) is
parsed so the following `<script>` becomes attributes of the open tag,
leaving the user's JS visible as text instead of running, with no
indication why.

Add `id="mdn-play-js"` to the JS script element and, in the following
ready script, check via `document.querySelector("script#mdn-play-js")`
that the element is still a `<script>`. When it is not, warn the user
via the existing console proxy.
User CSS containing `</style` or JS containing `</script` (for example
inside a string) terminates the `<style>` or `<script>` element early,
corrupting the page and allowing stray markup after it.

Escape those sequences by inserting a backslash (`<\/style`, `<\/script`)
before interpolating `css` and `js`. The backslash stops the HTML parser
from ending the element while remaining equivalent inside CSS/JS strings,
where `\/` resolves to `/`. The `escapeScriptText` doc comment records
the context-bound nature of that equivalence and the `<!--` ... `<script`
known limitation.
@caugner
caugner force-pushed the 1440-playground-runner-breakout-guard branch from 20f59b0 to b5e6b5c Compare July 17, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants