feat(docs): copy markdown + share-link in ask widget#23294
Queued
AztecBot wants to merge 3 commits into
Queued
Conversation
- Sanitize source hrefs in fromWire so a crafted `#share=` payload can't inject javascript:/data:/protocol-relative URLs into the anchor tags rendered by Message.jsx. - Cap encoded token at 32 KiB on decode and stream decompression with a 256 KiB inflated-output cap to neutralise gzip bombs. - Track userInteractedRef so a slow share-decode resolving after the user opens the launcher / sends / resets can't clobber the local conversation. - Treat window.prompt cancel as failed copy instead of flashing 'Link copied'. - Move textarea cleanup into finally so a throw during execCommand can't leak the hidden node into the DOM. - Drop the no-op gzip fallback and the stale Feedback banner comment.
The WHATWG URL parser normalizes backslashes to forward slashes for special schemes, so inputs like \\evil/x, /\\evil/x, and https:/\\evil/x round-trip through new URL() into external origins. Reject any href containing a backslash so the rendered anchor href never reaches the browser parser with a host-injecting payload.
critesjosh
approved these changes
May 15, 2026
Any commits made after this event will not be merged.
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.
Mirrors the two features just landed in honk-ai#131 over to
AztecDocsWidget, which is whatdocs.aztec.networkactually ships (honk-ai's/askis a separate frontend). Same UX, same security posture.What it does
1. Copy raw markdown
Small Copy chip on each assistant message header. Writes the raw markdown text (with backticks, headers, lists, fences) to the clipboard so it survives a paste into Slack/Notion/GitHub. Uses the async Clipboard API where available and falls back to a hidden
<textarea>+document.execCommand("copy")for sandboxed iframes / older WebViews.2. Share link
Share button in the panel header (visible once the conversation has at least one finished reply). It encodes the current Q&A as
JSON → UTF-8 → gzip (CompressionStream) → base64url, slots it into the URL hash as…/<page>#share=<blob>, and copies the link.When someone opens that link:
#share=…on mount, decodes locally, replays the transcript, and auto-opens the panelhistory.replaceStateso a refresh doesn't reload the old transcript over their new oneThe encoded blob never leaves the browser — URL fragments are not sent to the origin, so this preserves the existing anonymous-no-persist posture (no DB, no new endpoints, no backend touch). A roundtrip of a small conversation lands around ~280 bytes; the codec hard-caps encoded output at 32 KiB.
Implementation notes
docs/src/components/AztecDocsWidget/share.js— versioned wire format{ v: 1, m: [{ r: "u"|"b", t, s? }] }, plusreadShareHash/buildShareUrl/clearShareHashhelpers and a sharedcopyToClipboardhelper reused by the Copy button.index.jsx— hash-replayuseEffecton mount that pairs flat{role,text}entries back into the widget's{prompt, response, sources}message shape;handleSharecallback; clearsviewingShared/ hash on newhandleSendorhandleReset.Panel.jsx— Share button in the header (styled inline to read theme tokens, with.azw-share-btn.is-ok / .is-failoverrides for the post-click state); shared-conversation banner above the body.Message.jsx—CopyMarkdownButtonrendered in the assistant role header on completed (non-streaming, non-empty) replies, after the existing feedback wiring from feat(docs): user feedback + surfaced error frames in docs ask widget #23288.styles.css— minimal additions for the share-button success/fail states.Test plan
yarn preprocess && yarn docusaurus build— clean (the two broken-anchor warnings are pre-existing in the CLI reference, unrelated to this change)node --checkonshare.jsnull)Created by claudebox · group:
slackbot