CommandCodeAI / CommandCodeAI/command-code

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

Offen
#873 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Vorherrschende Sprache
Keine Sprachdaten
Sterne
4k
Forks
350
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

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.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Verfolge classifyShellCommand durch shellPermissionRulesForCommand, getShellPermissionChoices und ShellPermissionPrompt, und reproduziere anschließend den Fehler mit shell-quote's parse('echo ${}'). Stelle sicher, dass ein nicht parsbarer Befehl die Sitzung nicht mehr beendet, ein konservatives Genehmigungsverhalten verwendet und der Parse-Fehler in der Eingabeaufforderung angezeigt wird.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
javascript, node.js, shell
Bereich
cli, security
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Aktiv
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
72/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.