fix(extensions): harden Windows cmd launch in /diff and /files (#2329)

closes #2288
This commit is contained in:
myu003
2026-03-18 10:44:02 +08:00
committed by GitHub
parent 6a95f6882c
commit 16a010fd21
2 changed files with 27 additions and 2 deletions

View File

@@ -66,9 +66,20 @@ export default function (pi: ExtensionAPI) {
return;
}
const WINDOWS_UNSAFE_CMD_CHARS_RE = /[&|<>^%\r\n]/;
const quoteCmdArg = (value: string) => `"${value.replace(/"/g, '""')}"`;
const openWithCode = async (file: string) => {
if (process.platform === "win32") {
return pi.exec("cmd", ["/d", "/s", "/c", "code", "-g", file], { cwd: ctx.cwd });
if (WINDOWS_UNSAFE_CMD_CHARS_RE.test(file)) {
ctx.ui.notify(
`Refusing to open ${file}: path contains Windows cmd metacharacters (& | < > ^ % or newline).`,
"error",
);
return null;
}
const commandLine = `code -g ${quoteCmdArg(file)}`;
return pi.exec("cmd", ["/d", "/s", "/c", commandLine], { cwd: ctx.cwd });
}
return pi.exec("code", ["-g", file], { cwd: ctx.cwd });
};
@@ -79,6 +90,7 @@ export default function (pi: ExtensionAPI) {
// For untracked files, git difftool won't work, so fall back to just opening the file.
if (fileInfo.status === "?") {
const openResult = await openWithCode(fileInfo.file);
if (!openResult) return;
if (openResult.code !== 0) {
const openStderr = openResult.stderr.trim();
ctx.ui.notify(
@@ -104,6 +116,7 @@ export default function (pi: ExtensionAPI) {
);
const openResult = await openWithCode(fileInfo.file);
if (!openResult) return;
if (openResult.code !== 0) {
const openStderr = openResult.stderr.trim();
ctx.ui.notify(

View File

@@ -89,9 +89,20 @@ export default function (pi: ExtensionAPI) {
// Sort by most recent first
const files = Array.from(fileMap.values()).sort((a, b) => b.lastTimestamp - a.lastTimestamp);
const WINDOWS_UNSAFE_CMD_CHARS_RE = /[&|<>^%\r\n]/;
const quoteCmdArg = (value: string) => `"${value.replace(/"/g, '""')}"`;
const openWithCode = async (path: string) => {
if (process.platform === "win32") {
return pi.exec("cmd", ["/d", "/s", "/c", "code", "-g", path], { cwd: ctx.cwd });
if (WINDOWS_UNSAFE_CMD_CHARS_RE.test(path)) {
ctx.ui.notify(
`Refusing to open ${path}: path contains Windows cmd metacharacters (& | < > ^ % or newline).`,
"error",
);
return null;
}
const commandLine = `code -g ${quoteCmdArg(path)}`;
return pi.exec("cmd", ["/d", "/s", "/c", commandLine], { cwd: ctx.cwd });
}
return pi.exec("code", ["-g", path], { cwd: ctx.cwd });
};
@@ -99,6 +110,7 @@ export default function (pi: ExtensionAPI) {
const openSelected = async (file: FileEntry): Promise<void> => {
try {
const openResult = await openWithCode(file.path);
if (!openResult) return;
if (openResult.code !== 0) {
const openStderr = openResult.stderr.trim();
ctx.ui.notify(