From ab402bf1d9bdf5ab0712313681725f08b49dc98a Mon Sep 17 00:00:00 2001 From: daniel-lxs Date: Tue, 23 Sep 2025 15:06:27 -0500 Subject: [PATCH] fix: improve vscode-cdn.net URL validation and add copy action check - Fixed CodeQL security issue by properly validating vscode-cdn.net domain instead of substring check - Added missing copy action check for HTTPS/vscode-cdn URLs before opening image - Updated tests to match the more secure URL validation logic --- .../misc/__tests__/image-handler.spec.ts | 17 ++++++++++------- src/integrations/misc/image-handler.ts | 8 ++++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/integrations/misc/__tests__/image-handler.spec.ts b/src/integrations/misc/__tests__/image-handler.spec.ts index d5871773f3..f61721f649 100644 --- a/src/integrations/misc/__tests__/image-handler.spec.ts +++ b/src/integrations/misc/__tests__/image-handler.spec.ts @@ -5,14 +5,17 @@ vi.mock("vscode", () => { const showErrorMessage = vi.fn() const file = vi.fn((p: string) => ({ fsPath: p, path: p, scheme: "file" })) const parse = (input: string) => { - if (input.startsWith("https://") && input.includes("vscode-cdn.net")) { + if (input.startsWith("https://")) { const url = new URL(input) - return { - scheme: "https", - authority: url.host, - path: url.pathname, - fsPath: url.pathname, - with: vi.fn(), + // More secure check: ensure vscode-cdn.net is the actual domain, not just a substring + if (url.host === "vscode-cdn.net" || url.host.endsWith(".vscode-cdn.net")) { + return { + scheme: "https", + authority: url.host, + path: url.pathname, + fsPath: url.pathname, + with: vi.fn(), + } } } if (input.startsWith("file://")) { diff --git a/src/integrations/misc/image-handler.ts b/src/integrations/misc/image-handler.ts index d16a13ee32..f66c5a3123 100644 --- a/src/integrations/misc/image-handler.ts +++ b/src/integrations/misc/image-handler.ts @@ -10,7 +10,11 @@ export async function openImage(dataUriOrPath: string, options?: { values?: { ac // Example: https://file+.vscode-resource.vscode-cdn.net/file/ try { const u = vscode.Uri.parse(dataUriOrPath) - if (u.scheme === "https" && u.authority.includes("vscode-cdn.net")) { + if ( + u.scheme === "https" && + u.authority && + (u.authority === "vscode-cdn.net" || u.authority.endsWith(".vscode-cdn.net")) + ) { let fsPath = decodeURIComponent(u.path || "") // Strip the leading "/file/" prefix if present if (fsPath.startsWith("/file/")) { @@ -18,12 +22,12 @@ export async function openImage(dataUriOrPath: string, options?: { values?: { ac } fsPath = path.normalize(fsPath) if (fsPath) { - const fileUri = vscode.Uri.file(fsPath) if (options?.values?.action === "copy") { await vscode.env.clipboard.writeText(fsPath) vscode.window.showInformationMessage(t("common:info.path_copied_to_clipboard")) return } + const fileUri = vscode.Uri.file(fsPath) await vscode.commands.executeCommand("vscode.open", fileUri) return }