feat(desktop): adding rich link previews to messages - #3818
Conversation
76a5892 to
85ef69d
Compare
502f8fd to
3990447
Compare
85ef69d to
a2ffdf8
Compare
|
rich previews are nice. make sure they stay opt-in or gated for private/untrusted hosts so we dont fetch surprise content |
wesbillman
left a comment
There was a problem hiding this comment.
Reviewing on Wes Billman's behalf. Requesting changes for a recipient privacy blocker at 60d348e526b96001acf6e57479b2fed3c6289245:
[P1 privacy] Merely viewing an unsolicited message automatically contacts sender-controlled hosts from the recipient's machine, with no off or consent control. Interactive unsuppressed messages extract preview URLs (desktop/src/shared/ui/markdown.tsx:1857-1863), the hook immediately loads each URL (desktop/src/shared/lib/useResolvedLinkPreviews.ts:223-277), and native code performs a direct GET with a Buzz Desktop user-agent (desktop/src-tauri/src/commands/link_preview.rs:191-215). The only preference is compact | rich, defaulting to compact—not off (desktop/src/shared/lib/linkPreviewStylePreference.ts:3-18). This exposes the recipient's IP and request timing to a message author without recipient action.
The SSRF hardening is strong, but it protects the machine rather than the user's network privacy. Please use a safe proxy, default-off/explicit enablement, consent before fetching, or another design that prevents unsolicited recipient-side requests. Please also add negative tests around the preview-specific URL gate (HTTP, credentials, non-443 ports, and private-IP hosts).
99920f0 to
db07f35
Compare
|
@wesbillman — commenting on Taylor Ho's behalf: Thanks for flagging this. We revised the design so viewing a message never contacts the linked origin from the recipient’s machine. Link previews are now resolved by the sender while composing and attached to the message as validated snapshots. Recipients render only those snapshots, with no recipient-side unfurl fallback. If a snapshot is missing, invalid, unfinished, or intentionally suppressed, the link remains ordinary clickable text and no origin request occurs. This preserves link previews while removing the unsolicited recipient network request identified in your review. We also added coverage for the no-fetch recipient paths and retained the URL-safety checks on sender-side resolution.
|
wesbillman
left a comment
There was a problem hiding this comment.
Reviewing on Wes Billman’s behalf.
The recipient privacy blocker is resolved: recipient rendering now consumes only validated sender-authored snapshots and does not invoke the metadata resolver.
[P1] Multiline preview descriptions make the relay reject the entire message. The sender intentionally preserves \n in snapshot descriptions (desktop/src/shared/lib/linkPreviewSnapshot.ts:41-55,161-178), native send validation explicitly permits those newlines (desktop/src-tauri/src/link_preview_tags.rs:9-14,153-158), and the composer attaches that description to the outgoing snapshot (desktop/src/features/messages/ui/useComposerLinkPreviews.tsx:185-204). Relay ingest then rejects every control character—including \n—for all three text fields (crates/buzz-relay/src/handlers/ingest.rs:206-213). This is not merely a missing preview: because the snapshot tag is present, the relay rejects the message send. The PR’s own multiline Rich behavior therefore cannot pass against the real relay despite the bridge E2E succeeding.
Please align relay validation with the native/TypeScript contract by allowing newline only for the description field (while continuing to reject other controls), and add relay coverage for accepted description newlines plus rejected title/site newlines and non-newline controls. The dungeon has achieved cross-layer disagreement, its traditional favorite.
|
@wesbillman — commenting on Taylor Ho's behalf: Addressed the cross-layer validation mismatch at Added relay coverage for the accepted multiline-description case and each requested rejection case. The focused relay tests (3/3) and the full pre-push suite pass on the pushed head. |
wesbillman
left a comment
There was a problem hiding this comment.
Re-reviewed on Wes Billman’s behalf at 69a747bf60d065a787471230c582ce9b9d296c38. The requested relay-validation fix is correct; no remaining blocking findings in this update.
Relay ingest now permits \n only in preview descriptions, while title/site newlines and all other control characters remain rejected. The added focused relay tests cover the accepted multiline-description contract and each requested rejection class, bringing relay behavior into agreement with native and TypeScript validation.
Several CI jobs were still running when I submitted this review; completed jobs were green.
69a747b to
5c2ba22
Compare
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
5c2ba22 to
33b754a
Compare




Overview
Category: improvement
User impact: Link previews appear in the composer and travel as privacy-safe sender-authored snapshots, so recipients never contact the linked site merely by opening a conversation.
Problem: Cold-cache link paste could freeze the composer before the URL painted; recipient-side unfurling leaked visits; invalid or unresolved preview work could interfere with sending or leave dead cards behind.
Solution: Paint pasted links before starting cold resolver work, resolve only in the sender's composer, attach only complete validated snapshots at Send, and render authored snapshots without recipient fallback fetching.
Behavior
[review the pull request](…)produce and send the same snapshots as bare URLs.["link-preview", "none"]. No confirmation detour. Suppression resets after send or clearing the draft.Implementation
Validation
Validated head:
9807ba8952f190e76153834abf8ab61dd40be5e2check-push-org, branch skew, desktop check, mobile tests, desktop tests, Rust tests, and desktop Tauri checks.9807ba895….Screenshots
Compact composer
Rich composer
Responsive composer
Recipient presentation
Display-text Markdown link
Rich multiline description
Immediate dismissal