You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The capture side (snapshotterInjected.ts) empties on* attribute values and skips IFRAME srcdoc/sandbox, but the renderer has no corresponding checks. A crafted trace file bypasses the capture side entirely.
escapeHTMLAttribute does not help because payloads like alert(1) contain no characters that need escaping (&, <, >, ", '). The invalid src="x" triggers onerror automatically when the snapshot renders.
escapeHTMLAttribute escapes < to < and " to ", but the browser decodes HTML entities in attribute values before parsing srcdoc content, 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 + onerror pattern. A similar innerHTML + onerror vulnerability in SiYuan Note (CVE-2026-33066) escalated to full RCE in Electron.
Fix
Strip on* attributes entirely (continue in the attribute loop)
Normalize tag names to uppercase for isFrame, isAnchor, isImg, isMeta comparisons (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 comparisons
tests/library/snapshot-renderer.spec.ts: 5 new unit tests covering on* stripping, srcdoc/sandbox neutralization, and case-insensitive bypass prevention
Follows the defense-in-depth pattern established in #40655, #40115, and #14325. See also #19992 (traces as untrusted data) and #40533 (trace sanitization feature request).
…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.
7 failed
❌ [chromium] › mcp/annotate.spec.ts:173 › user-initiated annotate downloads zip with feedback.md @mcp-ubuntu-latest-chromium
❌ [firefox] › mcp/annotate.spec.ts:173 › user-initiated annotate downloads zip with feedback.md @mcp-ubuntu-latest-firefox
❌ [webkit] › mcp/annotate.spec.ts:273 › should enter annotate mode on fresh dashboard.tsx mount with -s --annotate @mcp-windows-latest-webkit
❌ [webkit] › mcp/annotate.spec.ts:297 › should annotate via direct browser_annotate MCP call @mcp-windows-latest-webkit
❌ [webkit] › mcp/annotate.spec.ts:330 › should annotate when context has no fixed viewport @mcp-windows-latest-webkit
❌ [webkit] › mcp/annotate.spec.ts:367 › should cancel browser_annotate when the MCP request is aborted @mcp-windows-latest-webkit
❌ [webkit] › mcp/config.spec.ts:138 › browser_get_config returns merged config from file, env and cli @mcp-windows-latest-webkit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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).