fix(trace-viewer): strip event handlers and neutralize IFRAME srcdoc/sandbox in snapshot renderer#40676
fix(trace-viewer): strip event handlers and neutralize IFRAME srcdoc/sandbox in snapshot renderer#40676SebTardif wants to merge 2 commits intomicrosoft:mainfrom
Conversation
…sandbox in snapshot renderer The snapshot renderer did not filter event handler attributes (on*) or neutralize IFRAME srcdoc/sandbox attributes. A crafted trace file could exploit these gaps: - onerror/onclick handlers execute without escaping because payloads like "alert(1)" contain no characters that escapeHTMLAttribute would modify - srcdoc with embedded HTML/script executes automatically because the browser decodes HTML entities in attribute values, undoing the escapeHTMLAttribute encoding Strip on* attributes entirely and rename srcdoc/sandbox to __playwright_srcdoc__/__playwright_sandbox__ (same pattern used for iframe src).
…sandbox in snapshot renderer The snapshot renderer did not filter event handler attributes (on*) or neutralize IFRAME srcdoc/sandbox attributes. A crafted trace file could exploit these gaps: - on* handlers (e.g. onerror, onclick) render as live event handlers because payloads like "alert(1)" contain no characters that escapeHTMLAttribute would modify. An IMG with onerror + invalid src fires automatically with no user interaction. - srcdoc with embedded HTML/script executes automatically because the browser decodes HTML entities in attribute values, undoing escapeHTMLAttribute encoding. - sandbox could alter the iframe security policy. Also fix case-sensitivity in tag name comparisons: isFrame, isAnchor, isImg, isMeta, and isSourceInsidePicture now use toUpperCase() to prevent bypasses via lowercase tag names in crafted traces.
Test results for "MCP"7 failed 7008 passed, 1058 skipped Merge workflow run. |
Test results for "tests 1"2 flaky41688 passed, 851 skipped Merge workflow run. |
Summary
on*event handler attributes and neutralize IFRAMEsrcdoc/sandboxin the snapshot rendererProblem
The capture side (
snapshotterInjected.ts) emptieson*attribute values and skips IFRAMEsrcdoc/sandbox, but the renderer has no corresponding checks. A crafted trace file bypasses the capture side entirely.Vector 1: Event handler attributes (zero interaction)
escapeHTMLAttributedoes not help because payloads likealert(1)contain no characters that need escaping (&,<,>,",'). The invalidsrc="x"triggersonerrorautomatically when the snapshot renders.Vector 2: IFRAME srcdoc (zero interaction)
escapeHTMLAttributeescapes<to<and"to", but the browser decodes HTML entities in attribute values before parsingsrcdoccontent, undoing the escaping entirely.Both vectors were confirmed to execute automatically in Chromium with no user interaction.
Attack surface: Trace files are shared between team members, uploaded as CI artifacts, and opened on trace.playwright.dev. AI coding agents (OpenClaw, Claude Code) that browse untrusted sites generate traces that developers then inspect. The OpenClaw project has had stored XSS in its own session viewer from the same
innerHTML+onerrorpattern. A similarinnerHTML+onerrorvulnerability in SiYuan Note (CVE-2026-33066) escalated to full RCE in Electron.Fix
on*attributes entirely (continuein the attribute loop)srcdocandsandboxto__playwright_srcdoc__/__playwright_sandbox__(same pattern used forsrcsince fix(trace-viewer): block meta refresh and sandbox snapshot iframes #40115)isFrame,isAnchor,isImg,isMetacomparisons (the pre-existing comparisons were case-sensitive, allowing a crafted trace to bypass them with lowercase tag names)Changes
packages/isomorphic/trace/snapshotRenderer.ts: Attribute filtering + case-insensitive tag comparisonstests/library/snapshot-renderer.spec.ts: 5 new unit tests coveringon*stripping,srcdoc/sandboxneutralization, and case-insensitive bypass preventionFollows the defense-in-depth pattern established in #40655, #40115, and #14325. See also #19992 (traces as untrusted data) and #40533 (trace sanitization feature request).