Bug Description
ClaudeCode.Adapter.Port.shell_escape/1 uses an allowlist of 12 shell-special characters (@shell_special_chars) to decide whether a string needs quoting. Characters not in this list — including !, #, <, >, ?, [, ], {, }, *, ~, and tab — pass through unquoted, which can break the shell command built by build_shell_command/4.
This is a problem because environment variable values (including API keys, user-provided env vars, and system vars like LS_COLORS) may contain any of these characters.
Example
An API key or env var value like Nk>m]R62!bu#s45#G3?6R<vw] would not be quoted, producing a broken shell command with unmatched redirections, glob patterns, and history expansion.
Root Cause
The allowlist approach (@shell_special_chars) is inherently fragile — it requires enumerating every dangerous character. Missing any one character creates a bug.
Fix
Invert the logic: define a pattern of known-safe characters and single-quote everything else. This is defense-in-depth — unknown characters are quoted by default.
Affected Code
lib/claude_code/adapter/port.ex — @shell_special_chars (line 34) and shell_escape/1 (lines 507-518)
Bug Description
ClaudeCode.Adapter.Port.shell_escape/1uses an allowlist of 12 shell-special characters (@shell_special_chars) to decide whether a string needs quoting. Characters not in this list — including!,#,<,>,?,[,],{,},*,~, and tab — pass through unquoted, which can break the shell command built bybuild_shell_command/4.This is a problem because environment variable values (including API keys, user-provided env vars, and system vars like
LS_COLORS) may contain any of these characters.Example
An API key or env var value like
Nk>m]R62!bu#s45#G3?6R<vw]would not be quoted, producing a broken shell command with unmatched redirections, glob patterns, and history expansion.Root Cause
The allowlist approach (
@shell_special_chars) is inherently fragile — it requires enumerating every dangerous character. Missing any one character creates a bug.Fix
Invert the logic: define a pattern of known-safe characters and single-quote everything else. This is defense-in-depth — unknown characters are quoted by default.
Affected Code
lib/claude_code/adapter/port.ex—@shell_special_chars(line 34) andshell_escape/1(lines 507-518)