From 691ce222370835d07b5e2b1c4d89db2deb085801 Mon Sep 17 00:00:00 2001
From: Peter Schuster
Date: Wed, 22 Jul 2026 20:40:37 +0200
Subject: [PATCH] fix(amazonq): make cmd.exe builtin detection
locale-independent
resolveWindowsCommand probed 'cmd.exe /c help ' and looked for the
English 'not supported by the help utility' marker. That string is
localized, so on non-English Windows (e.g. German) every unknown command
was treated as a valid builtin and passed validation.
Replace the probe with a static set of cmd.exe internal commands and
check it before falling back to 'where' for external commands.
---
.../agenticChat/tools/executeBash.test.ts | 11 +++
.../agenticChat/tools/executeBash.ts | 74 ++++++++++++++-----
2 files changed, 68 insertions(+), 17 deletions(-)
diff --git a/server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/executeBash.test.ts b/server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/executeBash.test.ts
index 279c87603e..966bb8372e 100644
--- a/server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/executeBash.test.ts
+++ b/server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/executeBash.test.ts
@@ -62,6 +62,17 @@ describe('ExecuteBash Tool', () => {
)
})
+ it('pass validation for a cmd.exe builtin without an executable on PATH', async function () {
+ // Builtins like 'assoc' have no .exe that 'where' can resolve, so they must be
+ // recognized as internal commands. This is only meaningful on Windows.
+ if (process.platform !== 'win32') {
+ this.skip()
+ return
+ }
+ const execBash = new ExecuteBash(features)
+ await execBash.validate({ command: 'assoc' })
+ })
+
it('validate and invokes the command', async () => {
const execBash = new ExecuteBash(features)
diff --git a/server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/executeBash.ts b/server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/executeBash.ts
index 6533cf2cd4..f346ceb211 100644
--- a/server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/executeBash.ts
+++ b/server/aws-lsp-codewhisperer/src/language-server/agenticChat/tools/executeBash.ts
@@ -751,8 +751,64 @@ export class ExecuteBash {
}
}
+ // cmd.exe internal commands that have no executable on PATH, so 'where' cannot find them.
+ // Kept as a static set because probing 'cmd.exe /c help ' is locale-dependent: the
+ // "not supported" marker is localized (e.g. German Windows), which made every unknown
+ // command pass validation on non-English systems.
+ private static readonly CMD_BUILTINS = new Set([
+ 'assoc',
+ 'break',
+ 'call',
+ 'cd',
+ 'chdir',
+ 'cls',
+ 'color',
+ 'copy',
+ 'date',
+ 'del',
+ 'dir',
+ 'dpath',
+ 'echo',
+ 'endlocal',
+ 'erase',
+ 'exit',
+ 'for',
+ 'ftype',
+ 'goto',
+ 'if',
+ 'md',
+ 'mkdir',
+ 'mklink',
+ 'move',
+ 'path',
+ 'pause',
+ 'popd',
+ 'prompt',
+ 'pushd',
+ 'rd',
+ 'rem',
+ 'ren',
+ 'rename',
+ 'rmdir',
+ 'set',
+ 'setlocal',
+ 'shift',
+ 'start',
+ 'time',
+ 'title',
+ 'type',
+ 'ver',
+ 'verify',
+ 'vol',
+ ])
+
private static async resolveWindowsCommand(logger: Logging, cmd: string): Promise {
- // 1. Check for external command or alias
+ // 1. Check for built-in command
+ if (ExecuteBash.CMD_BUILTINS.has(cmd.toLowerCase())) {
+ return
+ }
+
+ // 2. Check for external command or alias
try {
const whereProc = new processUtils.ChildProcess(logger, 'where', [cmd], {
collect: true,
@@ -768,22 +824,6 @@ export class ExecuteBash {
logger.debug(`'where ${cmd}' failed: ${(err as Error).message}`)
}
- // 2. Check for built-in command
- try {
- const helpProc = new processUtils.ChildProcess(logger, 'cmd.exe', ['/c', 'help', cmd], {
- collect: true,
- waitForStreams: true,
- })
- const result = await helpProc.run()
- const output = result.stdout.trim()
-
- if (output && !output.includes('This command is not supported by the help utility')) {
- return
- }
- } catch (err) {
- logger.debug(`'help ${cmd}' failed: ${(err as Error).message}`)
- }
-
throw new Error(`Command '${cmd}' not found as executable or Windows built-in command`)
}