From ad3746d5b3a7b235c93e8032d984d32f7328187a Mon Sep 17 00:00:00 2001 From: Wes Date: Wed, 3 Jun 2026 09:02:21 -0600 Subject: [PATCH 1/2] fix: native arbitrary-file download + image context-menu flash Two regressions in message media handling: 1. Arbitrary file downloads (FileCard, added in #810) used a bare ``. In the Tauri webview that navigates to the blob URL, escaping to the OS browser and landing on the Block CDN "browser not supported" interstitial. Add a native `download_file` Tauri command mirroring `download_image`'s SSRF `/media/`-origin validation, 50 MiB streaming cap, and MIME blocklist, but with a generic save dialog and a sanitized imeta filename. FileCard is now a ` ); } @@ -647,7 +673,12 @@ function createMarkdownComponents( -
+
{ + if (e.button !== 0) e.preventDefault(); + }} + > {alt}[0], diff --git a/desktop/tests/e2e/file-attachment.spec.ts b/desktop/tests/e2e/file-attachment.spec.ts index 8c54dc7bb..c8e2968c9 100644 --- a/desktop/tests/e2e/file-attachment.spec.ts +++ b/desktop/tests/e2e/file-attachment.spec.ts @@ -39,16 +39,24 @@ test("upload a file and see a FileCard in the timeline", async ({ page }) => { // Send the (attachment-only) message. await page.getByTestId("send-message").click(); - // A FileCard renders in the timeline: a download link carrying the filename - // and pointing at the blob URL. + // A FileCard renders in the timeline: a button carrying the filename. It + // downloads via the native `download_file` command (HTTP inside the app's + // tunnel + save dialog), NOT a plain `` link — a bare link + // escapes the webview to the OS browser and hits a corporate CDN page. const card = page.getByTestId("file-card"); await expect(card).toBeVisible(); await expect(card).toContainText("quarterly-report.pdf"); - await expect(card).toHaveAttribute( - "href", - `https://mock.relay/media/${"a".repeat(64)}.pdf`, - ); - await expect(card).toHaveAttribute("download", "quarterly-report.pdf"); + + await card.click(); + await expect + .poll(() => + page.evaluate( + () => + (window as Window & { __SPROUT_E2E_COMMANDS__?: string[] }) + .__SPROUT_E2E_COMMANDS__ ?? [], + ), + ) + .toContain("download_file"); }); test("forum posts emit a FileCard for generic attachments, not a broken image", async ({ @@ -75,14 +83,20 @@ test("forum posts emit a FileCard for generic attachments, not a broken image", await page.getByTestId("send-message").click(); // The post renders through the shared Markdown component as a FileCard — - // a download link carrying the filename and pointing at the blob URL — NOT - // an inline image. + // a button carrying the filename that downloads via the native + // `download_file` command — NOT an inline image and NOT a bare link. const card = page.getByTestId("file-card"); await expect(card).toBeVisible(); await expect(card).toContainText("quarterly-report.pdf"); - await expect(card).toHaveAttribute( - "href", - `https://mock.relay/media/${"a".repeat(64)}.pdf`, - ); - await expect(card).toHaveAttribute("download", "quarterly-report.pdf"); + + await card.click(); + await expect + .poll(() => + page.evaluate( + () => + (window as Window & { __SPROUT_E2E_COMMANDS__?: string[] }) + .__SPROUT_E2E_COMMANDS__ ?? [], + ), + ) + .toContain("download_file"); }); From 94e8a1437d445405ac982184d64cdb71ed84ce6f Mon Sep 17 00:00:00 2001 From: Wes Date: Wed, 3 Jun 2026 10:25:14 -0600 Subject: [PATCH 2/2] fix: keep forum FileCard clickable by memoizing imeta map ForumPostCard rendered , building a fresh imeta object on every render. The Markdown component's React.memo compares imetaByUrl by reference, so the memo never held for forum posts: react-markdown re-parsed and rebuilt the FileCard