mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
feat(core): address review comments and fix strict sandbox shell selection
This commit is contained in:
@@ -273,7 +273,12 @@ public class GeminiSandbox {
|
|||||||
si.hStdOutput = GetStdHandle(-11);
|
si.hStdOutput = GetStdHandle(-11);
|
||||||
si.hStdError = GetStdHandle(-12);
|
si.hStdError = GetStdHandle(-12);
|
||||||
|
|
||||||
string commandLine = string.Join(" ", args, 2, args.Length - 2);
|
List<string> quotedArgs = new List<string>();
|
||||||
|
for (int i = 2; i < args.Length; i++) {
|
||||||
|
quotedArgs.Add(QuoteArgument(args[i]));
|
||||||
|
}
|
||||||
|
string commandLine = string.Join(" ", quotedArgs.ToArray());
|
||||||
|
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
if (!CreateProcessAsUser(hRestrictedToken, null, commandLine, IntPtr.Zero, IntPtr.Zero, true, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT, IntPtr.Zero, cwd, ref si, out pi)) {
|
if (!CreateProcessAsUser(hRestrictedToken, null, commandLine, IntPtr.Zero, IntPtr.Zero, true, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT, IntPtr.Zero, cwd, ref si, out pi)) {
|
||||||
Console.Error.WriteLine("Failed to create process. Error: " + Marshal.GetLastWin32Error());
|
Console.Error.WriteLine("Failed to create process. Error: " + Marshal.GetLastWin32Error());
|
||||||
@@ -299,6 +304,14 @@ public class GeminiSandbox {
|
|||||||
return (int)exitCode;
|
return (int)exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string QuoteArgument(string arg) {
|
||||||
|
if (string.IsNullOrEmpty(arg)) return "\"\"";
|
||||||
|
if (arg.IndexOfAny(new char[] { ' ', '\t', '\n', '\v', '\"' }) == -1) return arg;
|
||||||
|
|
||||||
|
string escaped = arg.Replace("\"", "\\\"");
|
||||||
|
return "\"" + escaped + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
private static int RunInImpersonation(IntPtr hToken, Func<int> action) {
|
private static int RunInImpersonation(IntPtr hToken, Func<int> action) {
|
||||||
using (WindowsIdentity.Impersonate(hToken)) {
|
using (WindowsIdentity.Impersonate(hToken)) {
|
||||||
return action();
|
return action();
|
||||||
|
|||||||
@@ -279,6 +279,14 @@ export class ShellExecutionService {
|
|||||||
): Promise<ShellExecutionHandle> {
|
): Promise<ShellExecutionHandle> {
|
||||||
const sandboxManager =
|
const sandboxManager =
|
||||||
shellExecutionConfig.sandboxManager ?? new NoopSandboxManager();
|
shellExecutionConfig.sandboxManager ?? new NoopSandboxManager();
|
||||||
|
|
||||||
|
// Strict sandbox on Windows (network disabled) requires cmd.exe
|
||||||
|
const isStrictSandbox =
|
||||||
|
os.platform() === 'win32' &&
|
||||||
|
shellExecutionConfig.sandboxConfig?.enabled &&
|
||||||
|
shellExecutionConfig.sandboxConfig?.command === 'windows-native' &&
|
||||||
|
!shellExecutionConfig.sandboxConfig?.networkAccess;
|
||||||
|
|
||||||
const { env: sanitizedEnv } = await sandboxManager.prepareCommand({
|
const { env: sanitizedEnv } = await sandboxManager.prepareCommand({
|
||||||
command: commandToExecute,
|
command: commandToExecute,
|
||||||
args: [],
|
args: [],
|
||||||
@@ -302,6 +310,7 @@ export class ShellExecutionService {
|
|||||||
shellExecutionConfig,
|
shellExecutionConfig,
|
||||||
ptyInfo,
|
ptyInfo,
|
||||||
sanitizedEnv,
|
sanitizedEnv,
|
||||||
|
isStrictSandbox,
|
||||||
);
|
);
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
// Fallback to child_process
|
// Fallback to child_process
|
||||||
@@ -316,6 +325,7 @@ export class ShellExecutionService {
|
|||||||
abortSignal,
|
abortSignal,
|
||||||
shellExecutionConfig.sanitizationConfig,
|
shellExecutionConfig.sanitizationConfig,
|
||||||
shouldUseNodePty,
|
shouldUseNodePty,
|
||||||
|
isStrictSandbox,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,10 +366,18 @@ export class ShellExecutionService {
|
|||||||
abortSignal: AbortSignal,
|
abortSignal: AbortSignal,
|
||||||
sanitizationConfig: EnvironmentSanitizationConfig,
|
sanitizationConfig: EnvironmentSanitizationConfig,
|
||||||
isInteractive: boolean,
|
isInteractive: boolean,
|
||||||
|
isStrictSandbox?: boolean,
|
||||||
): ShellExecutionHandle {
|
): ShellExecutionHandle {
|
||||||
try {
|
try {
|
||||||
const isWindows = os.platform() === 'win32';
|
const isWindows = os.platform() === 'win32';
|
||||||
const { executable, argsPrefix, shell } = getShellConfiguration();
|
let { executable, argsPrefix, shell } = getShellConfiguration();
|
||||||
|
|
||||||
|
if (isStrictSandbox) {
|
||||||
|
shell = 'cmd';
|
||||||
|
argsPrefix = ['/c'];
|
||||||
|
executable = 'cmd.exe';
|
||||||
|
}
|
||||||
|
|
||||||
const guardedCommand = ensurePromptvarsDisabled(commandToExecute, shell);
|
const guardedCommand = ensurePromptvarsDisabled(commandToExecute, shell);
|
||||||
const spawnArgs = [...argsPrefix, guardedCommand];
|
const spawnArgs = [...argsPrefix, guardedCommand];
|
||||||
|
|
||||||
@@ -690,6 +708,7 @@ export class ShellExecutionService {
|
|||||||
shellExecutionConfig: ShellExecutionConfig,
|
shellExecutionConfig: ShellExecutionConfig,
|
||||||
ptyInfo: PtyImplementation,
|
ptyInfo: PtyImplementation,
|
||||||
sanitizedEnv: Record<string, string | undefined>,
|
sanitizedEnv: Record<string, string | undefined>,
|
||||||
|
isStrictSandbox?: boolean,
|
||||||
): Promise<ShellExecutionHandle> {
|
): Promise<ShellExecutionHandle> {
|
||||||
if (!ptyInfo) {
|
if (!ptyInfo) {
|
||||||
// This should not happen, but as a safeguard...
|
// This should not happen, but as a safeguard...
|
||||||
@@ -700,7 +719,13 @@ export class ShellExecutionService {
|
|||||||
try {
|
try {
|
||||||
const cols = shellExecutionConfig.terminalWidth ?? 80;
|
const cols = shellExecutionConfig.terminalWidth ?? 80;
|
||||||
const rows = shellExecutionConfig.terminalHeight ?? 30;
|
const rows = shellExecutionConfig.terminalHeight ?? 30;
|
||||||
const { executable, argsPrefix, shell } = getShellConfiguration();
|
let { executable, argsPrefix, shell } = getShellConfiguration();
|
||||||
|
|
||||||
|
if (isStrictSandbox) {
|
||||||
|
shell = 'cmd';
|
||||||
|
argsPrefix = ['/c'];
|
||||||
|
executable = 'cmd.exe';
|
||||||
|
}
|
||||||
|
|
||||||
const resolvedExecutable = await resolveExecutable(executable);
|
const resolvedExecutable = await resolveExecutable(executable);
|
||||||
if (!resolvedExecutable) {
|
if (!resolvedExecutable) {
|
||||||
|
|||||||
Reference in New Issue
Block a user