From 2997a47fec54d1fcfda1b39e212cd50aa8cc9e72 Mon Sep 17 00:00:00 2001 From: Dotta Date: Mon, 1 Jun 2026 22:14:06 +0000 Subject: [PATCH] Guard markdown filename previews by content type Co-Authored-By: Paperclip --- .../IssueAttachmentsSection.test.tsx | 29 +++++++++++++++++++ ui/src/lib/issue-attachments.ts | 3 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/ui/src/components/IssueAttachmentsSection.test.tsx b/ui/src/components/IssueAttachmentsSection.test.tsx index 6fca448a..d9c3ff1b 100644 --- a/ui/src/components/IssueAttachmentsSection.test.tsx +++ b/ui/src/components/IssueAttachmentsSection.test.tsx @@ -153,6 +153,35 @@ describe("IssueAttachmentsSection", () => { }); }); + it("does not promote specific non-markdown content types by filename alone", async () => { + const attachment = makeAttachment({ + id: "zip-markdown", + originalFilename: "report.md", + contentType: "application/zip", + contentPath: "/api/attachments/zip-markdown/content", + openPath: "/api/attachments/zip-markdown/content", + downloadPath: "/api/attachments/zip-markdown/content?download=1", + }); + + await act(async () => { + root.render( + + + , + ); + }); + await flushReact(); + + expect(container.querySelector('[data-testid="markdown-body"]')).toBeNull(); + expect(container.textContent).toContain("report.md"); + expect(container.textContent).toContain("application/zip"); + expect(fetchSpy).not.toHaveBeenCalled(); + }); + it("renders video attachments through the same player used for artifact outputs", async () => { const attachment = makeAttachment({ id: "video-attachment", diff --git a/ui/src/lib/issue-attachments.ts b/ui/src/lib/issue-attachments.ts index 39534d48..8c6859da 100644 --- a/ui/src/lib/issue-attachments.ts +++ b/ui/src/lib/issue-attachments.ts @@ -63,5 +63,6 @@ export function isMarkdownAttachment( } const filename = (attachment.originalFilename ?? "").toLowerCase(); - return filename.endsWith(".md") || filename.endsWith(".markdown"); + if (!filename.endsWith(".md") && !filename.endsWith(".markdown")) return false; + return contentType === "text/plain" || GENERIC_ATTACHMENT_CONTENT_TYPES.has(contentType); }