Repository navigation
test: pin html escaping of clipboard link labels - #1166
Merged
Merged
Conversation
mention names, nameless chip text and link labels are read from the dom and escaped by the html serializer before the markdown path parses them back. pin that contract for each label source so an escaping regression fails the html and markdown round trip. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Kalvin Chau <[email protected]>
wesbillman
reviewed
Oct 15, 2026
wesbillman
left a comment
Collaborator
There was a problem hiding this comment.
🤖 Carl, an automated reviewer, commenting via Wes's GitHub account.
No blockers. The exact text/Markdown/HTML expectation covers all three label sources (mention attribute, nameless chip text, data-link-label). Local mutation check: dropping escapeHtml(label) in selection-copy.ts link() fails this test. Merges cleanly alongside #1162, which touches messageHtml (no-op there, single &).
wesbillman
approved these changes
Oct 15, 2026
johnmatthewtennant
added a commit
that referenced
this pull request
Oct 15, 2026
* origin/main: perf(css): replace wide :has() anchors with owner-set data attributes (#1180) fix(goose): share an MCP server pool and harden session lifecycle (#1142) test(browser): hold reading focus until the unread baseline is observed (#1182) Refine the profile menu and open status editing immediately (#1172) unify session naming, workspace and lifetime settings (#1079) perf(messages): stop forcing a layout on every action bar position frame (#1184) test(browser): prepare fixture dependencies once per run (#1126) test: replace fragile string assertions with precise checks (#1162) test: keep thread fixture errors out of http responses (#1163) feat: upgrade tauri and native plugins (#1169) test: pass native menu scripts to eval as arguments (#1160) test: cover shared link url policy (#1165) test: preserve literal text across markdown comment projection (#1164) test: pin html escaping of clipboard link labels (#1166) Preserve linked text pasted from other apps (#1069) fix(messages): keep the reader's message in place when a thread reply and layout change land together (#1130) Signed-off-by: John Tennant <[email protected]> # Conflicts: # src/bundled/channels/ChannelBody.tsx # src/bundled/channels/ConversationTab.tsx
johnmatthewtennant
pushed a commit
that referenced
this pull request
Oct 15, 2026
* commit 'f2595b8df20c9e6e91f79e77b52b700137063a49': (25 commits) Add community leave and device removal settings (#954) perf(css): replace wide :has() anchors with owner-set data attributes (#1180) fix(goose): share an MCP server pool and harden session lifecycle (#1142) test(browser): hold reading focus until the unread baseline is observed (#1182) Refine the profile menu and open status editing immediately (#1172) unify session naming, workspace and lifetime settings (#1079) perf(messages): stop forcing a layout on every action bar position frame (#1184) test(browser): prepare fixture dependencies once per run (#1126) test: replace fragile string assertions with precise checks (#1162) test: keep thread fixture errors out of http responses (#1163) feat: upgrade tauri and native plugins (#1169) test: pass native menu scripts to eval as arguments (#1160) test: cover shared link url policy (#1165) test: preserve literal text across markdown comment projection (#1164) test: pin html escaping of clipboard link labels (#1166) Preserve linked text pasted from other apps (#1069) fix(messages): keep the reader's message in place when a thread reply and layout change land together (#1130) separate session sharing from explicit channel conversion (#1070) feat(goose): bundle goose-acp with the app (#1110) feat(agents): answer unmentioned messages in one-to-one DMs (#1173) ... Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
Adds a regression test pinning HTML escaping of DOM-derived link labels in the message selection serializer (
src/features/messages/selection-copy.ts). No production code changes.The test feeds
"><img src=x onerror=alert(1)>through each label source that can carry markup — a mention'sdata-mention-name, a nameless chip's text, and a link'sdata-link-label— and asserts the exact text, Markdown and HTML output. The Markdown result goes through the serializer's own HTML read-back, so it also proves the payload stays text. Removing<>"escaping from labels while keeping&escaping was caught only by this test.Code-scanning disposition
These
js/xss-through-domalerts are false positives:alert 24,
alert 25,
alert 26,
alert 27,
alert 28,
alert 29,
alert 33.
link()through its Markdown or plain-text return. None passes theformat === "html"return, so CodeQL already recognizesescapeHtmlthere.serializeNode(..., "html")output. That format propagates unchanged throughserialize/childrenand always selects the escaped return.formatargument, so it can't tell that the other two returns never reach the sinks.profileKey,parseBuzzLinkandsafeLinkUrl.Alert 25 is in production code. The others are test read-backs in
selection-copy.test.tsxandEditableInput.test.tsx. The alerts remain open until dismissed; this PR does not change their state.Verification
pnpm check: pass.vitest run src/features/messages/selection-copy.test.tsx src/features/messages/EditableInput.test.tsx: 235/235 pass.escapeHtml(label)fromlink()fails the new test (HTML mismatch, and the Markdown read-back loses the label to a parsed<img>).scripts/check-push.mjs, plus--designand--clippy): pass.vitest runlocally: 6 failures (4 timeouts, 2 UI-query misses) inApp.profile,ChannelMembersDialogandInboxPageunder heavy machine load. Those three files pass 157/157 when run alone. Deferred to CI.🤖 Generated with Claude Code