CommandCodeAI / CommandCodeAI/command-code

CLI crashes (unhandled rejection) when a shell command contains a literal ${} — shell-quote parse throws in classifyShellCommand

未關閉
#873 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

主要語言
沒有語言資料
星號
4k
分支
350
PR 合併指標
30 天內沒有已合併 PR

描述

Summary

The CLI dies with an unhandled promise rejection when it builds the shell-permission prompt for a command whose text contains a literal ${}. shell-quote's parse() throws Bad substitution: ${}, and classifyShellCommandshellPermissionRulesForCommandgetShellPermissionChoicesShellPermissionPrompt does not catch it, so the whole session exits.

This is not a "bad command" problem: the command is never run, and the user never sees a prompt. The process is gone, and with it the conversation context of a long-running session.

Environment

command-code 1.54.1
node v24.1.0
OS macOS 27.0, arm64 (Apple Silicon, Homebrew install at /opt/homebrew)
shell-quote (bundled) 1.10.0
Session running inside tmux, driven by an automation harness (messages sent programmatically), auto-yes enabled

Stack trace (as printed)

✖ CRITICAL: Unhandled Promise Rejection!
✖ ERROR → Error
ℹ REASON → Bad substitution: ${}
ℹ ERROR STACK ↓
 Error: Bad substitution: ${}
    at parseEnvVar (/opt/homebrew/lib/node_modules/command-code/node_modules/shell-quote/parse.js:157:12)
    at /opt/homebrew/lib/node_modules/command-code/node_modules/shell-quote/parse.js:236:14
    at Array.map (<anonymous>)
    at parseInternal (/opt/homebrew/lib/node_modules/command-code/node_modules/shell-quote/parse.js:113:17)
    at parse (/opt/homebrew/lib/node_modules/command-code/node_modules/shell-quote/parse.js:309:15)
    at classify (file:///opt/homebrew/lib/node_modules/command-code/dist/cli.mjs:2:382298)
    at classifyShellCommand (file:///opt/homebrew/lib/node_modules/command-code/dist/cli.mjs:2:383445)
    at shellPermissionRulesForCommand (file:///opt/homebrew/lib/node_modules/command-code/dist/cli.mjs:2:1075519)
    at getShellPermissionChoices (file:///opt/homebrew/lib/node_modules/command-code/dist/cli.mjs:2:1083719)
    at ShellPermissionPrompt (file:///opt/homebrew/lib/node_modules/command-code/dist/cli.mjs:16:21387)

ℹ Trace ID: 2bf510fd5bd624f90b2282f692816b84

Minimal repro of the throwing dependency

shell-quote throws on a literal ${} (empty substitution), while every other ${...} form parses fine:

const { parse } = require('shell-quote'); // 1.10.0

parse('echo ${VAR}');          // ok
parse('echo ${#a[@]}');        // ok
parse('echo ${PIPESTATUS[0]}');// ok
parse('echo ${!v}');           // ok
parse('echo $(( 1 + 2 ))');    // ok

parse('echo ${}');             // throws: Bad substitution: ${}
parse('echo "${}"');           // throws: Bad substitution: ${}
parse('printf %s ${}');        // throws: Bad substitution: ${}

Source: shell-quote/parse.js parseEnvVar() throws when ${ is immediately followed by }.

How it happens in practice

The model writes a shell command whose text happens to contain ${} — for example when echoing or heredoc-ing documentation/templates that mention ${} literally, or when a variable name is interpolated into an empty string while composing the command. The CLI then tries to classify that command for the permission prompt and crashes before showing anything.

Expected behaviour

Classification of a command that cannot be parsed should degrade, not kill the process. Something like:

  1. wrap the shell-quote parse() call in try/catch inside classify / classifyShellCommand,
  2. on a parse error, fall back to the most conservative classification (treat the command as unrecognised and require explicit approval), and
  3. surface the parse error in the prompt instead of throwing.

A global unhandledRejection guard around the prompt path would also prevent a single classification bug from ending the session.

Impact

  • The CLI exits mid-run. In an orchestrated, multi-session setup the managing session dies and its conversation context is lost; recovery has to be done by hand from the run artifacts.
  • Because the crash is in the permission prompt path, --trust / auto-yes settings do not help: the process dies while building the prompt.

貢獻指南

這個儲存庫沒有索引到貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

研究方向

追蹤 classifyShellCommand 經過 shellPermissionRulesForCommand、getShellPermissionChoices 和 ShellPermissionPrompt,然後使用 shell-quote's parse('echo ${}') 重現該故障。確保無法解析的命令不再結束工作階段,採用保守的核准行為,並在提示中顯示解析錯誤。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
javascript, node.js, shell
領域
cli, security
Issue 類型
缺陷
難度
3/5
預估耗時
1-2 天
活躍度
活躍
描述清晰度
基本清楚
新手友好度
72/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。