fix(extensions): harden Windows cmd launch in /diff and /files (#2329)
closes #2288
This commit is contained in:
@@ -66,9 +66,20 @@ export default function (pi: ExtensionAPI) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WINDOWS_UNSAFE_CMD_CHARS_RE = /[&|<>^%\r\n]/;
|
||||||
|
const quoteCmdArg = (value: string) => `"${value.replace(/"/g, '""')}"`;
|
||||||
|
|
||||||
const openWithCode = async (file: string) => {
|
const openWithCode = async (file: string) => {
|
||||||
if (process.platform === "win32") {
|
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 });
|
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.
|
// For untracked files, git difftool won't work, so fall back to just opening the file.
|
||||||
if (fileInfo.status === "?") {
|
if (fileInfo.status === "?") {
|
||||||
const openResult = await openWithCode(fileInfo.file);
|
const openResult = await openWithCode(fileInfo.file);
|
||||||
|
if (!openResult) return;
|
||||||
if (openResult.code !== 0) {
|
if (openResult.code !== 0) {
|
||||||
const openStderr = openResult.stderr.trim();
|
const openStderr = openResult.stderr.trim();
|
||||||
ctx.ui.notify(
|
ctx.ui.notify(
|
||||||
@@ -104,6 +116,7 @@ export default function (pi: ExtensionAPI) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const openResult = await openWithCode(fileInfo.file);
|
const openResult = await openWithCode(fileInfo.file);
|
||||||
|
if (!openResult) return;
|
||||||
if (openResult.code !== 0) {
|
if (openResult.code !== 0) {
|
||||||
const openStderr = openResult.stderr.trim();
|
const openStderr = openResult.stderr.trim();
|
||||||
ctx.ui.notify(
|
ctx.ui.notify(
|
||||||
|
|||||||
@@ -89,9 +89,20 @@ export default function (pi: ExtensionAPI) {
|
|||||||
// Sort by most recent first
|
// Sort by most recent first
|
||||||
const files = Array.from(fileMap.values()).sort((a, b) => b.lastTimestamp - a.lastTimestamp);
|
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) => {
|
const openWithCode = async (path: string) => {
|
||||||
if (process.platform === "win32") {
|
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 });
|
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> => {
|
const openSelected = async (file: FileEntry): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const openResult = await openWithCode(file.path);
|
const openResult = await openWithCode(file.path);
|
||||||
|
if (!openResult) return;
|
||||||
if (openResult.code !== 0) {
|
if (openResult.code !== 0) {
|
||||||
const openStderr = openResult.stderr.trim();
|
const openStderr = openResult.stderr.trim();
|
||||||
ctx.ui.notify(
|
ctx.ui.notify(
|
||||||
|
|||||||
Reference in New Issue
Block a user