Tighten bash shell option handling (#12532)

This commit is contained in:
cornmander
2025-11-04 11:11:29 -05:00
committed by GitHub
parent 96d7eb2966
commit b8b6620365
4 changed files with 108 additions and 10 deletions
@@ -12,7 +12,7 @@ import { TextDecoder } from 'node:util';
import os from 'node:os';
import type { IPty } from '@lydell/node-pty';
import { getCachedEncodingForBuffer } from '../utils/systemEncoding.js';
import { getShellConfiguration } from '../utils/shell-utils.js';
import { getShellConfiguration, type ShellType } from '../utils/shell-utils.js';
import { isBinary } from '../utils/textUtils.js';
import pkg from '@xterm/headless';
import {
@@ -24,6 +24,22 @@ const { Terminal } = pkg;
const SIGKILL_TIMEOUT_MS = 200;
const MAX_CHILD_PROCESS_BUFFER_SIZE = 16 * 1024 * 1024; // 16MB
const BASH_SHOPT_OPTIONS = 'promptvars nullglob extglob nocaseglob dotglob';
const BASH_SHOPT_GUARD = `shopt -u ${BASH_SHOPT_OPTIONS};`;
function ensurePromptvarsDisabled(command: string, shell: ShellType): string {
if (shell !== 'bash') {
return command;
}
const trimmed = command.trimStart();
if (trimmed.startsWith(BASH_SHOPT_GUARD)) {
return command;
}
return `${BASH_SHOPT_GUARD} ${command}`;
}
/** A structured result from a shell command execution. */
export interface ShellExecutionResult {
/** The raw, unprocessed output buffer. */
@@ -190,8 +206,9 @@ export class ShellExecutionService {
): ShellExecutionHandle {
try {
const isWindows = os.platform() === 'win32';
const { executable, argsPrefix } = getShellConfiguration();
const spawnArgs = [...argsPrefix, commandToExecute];
const { executable, argsPrefix, shell } = getShellConfiguration();
const guardedCommand = ensurePromptvarsDisabled(commandToExecute, shell);
const spawnArgs = [...argsPrefix, guardedCommand];
const child = cpSpawn(executable, spawnArgs, {
cwd,
@@ -403,8 +420,9 @@ export class ShellExecutionService {
try {
const cols = shellExecutionConfig.terminalWidth ?? 80;
const rows = shellExecutionConfig.terminalHeight ?? 30;
const { executable, argsPrefix } = getShellConfiguration();
const args = [...argsPrefix, commandToExecute];
const { executable, argsPrefix, shell } = getShellConfiguration();
const guardedCommand = ensurePromptvarsDisabled(commandToExecute, shell);
const args = [...argsPrefix, guardedCommand];
const ptyProcess = ptyInfo.module.spawn(executable, args, {
cwd,