From 86b97da0b2ad28d4ee9d1cdf1077201a5aa9c7ff Mon Sep 17 00:00:00 2001 From: h0wdee Date: Mon, 20 Apr 2026 08:57:36 -0400 Subject: [PATCH] fix(opencode): validate clipboard content type on Linux On Linux, xclip/wl-paste output raw bytes even when clipboard contains text (not an image). The code only checked byteLength > 0, so text was incorrectly labeled as image/png and sent to the model, which failed with 'could not process image'. Use existing sniffAttachmentMime() to validate PNG magic bytes before returning clipboard content as an image. Fixes #23458 --- packages/opencode/src/cli/cmd/tui/util/clipboard.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/util/clipboard.ts b/packages/opencode/src/cli/cmd/tui/util/clipboard.ts index 8c535833c6ea..c1e858a481fc 100644 --- a/packages/opencode/src/cli/cmd/tui/util/clipboard.ts +++ b/packages/opencode/src/cli/cmd/tui/util/clipboard.ts @@ -5,6 +5,7 @@ import path from "path" import fs from "fs/promises" import * as Filesystem from "../../../../util/filesystem" import * as Process from "../../../../util/process" +import { sniffAttachmentMime } from "../../../../util/media" // Lazy load which and clipboardy to avoid expensive execa/which/isexe chain at startup const getWhich = lazy(async () => { @@ -93,13 +94,19 @@ export async function read(): Promise { if (os === "linux") { const wayland = await Process.run(["wl-paste", "-t", "image/png"], { nothrow: true }) if (wayland.stdout.byteLength > 0) { - return { data: Buffer.from(wayland.stdout).toString("base64"), mime: "image/png" } + const mime = sniffAttachmentMime(new Uint8Array(wayland.stdout), "text/plain") + if (mime === "image/png") { + return { data: Buffer.from(wayland.stdout).toString("base64"), mime: "image/png" } + } } const x11 = await Process.run(["xclip", "-selection", "clipboard", "-t", "image/png", "-o"], { nothrow: true, }) if (x11.stdout.byteLength > 0) { - return { data: Buffer.from(x11.stdout).toString("base64"), mime: "image/png" } + const mime = sniffAttachmentMime(new Uint8Array(x11.stdout), "text/plain") + if (mime === "image/png") { + return { data: Buffer.from(x11.stdout).toString("base64"), mime: "image/png" } + } } }