feat(config): add ShellQuote helper for safe env var escaping (#830)

Add ShellQuote function to properly escape environment variable values
containing shell special characters ({, }, *, $, ", etc.).

Changes:
- Add ShellQuote() that wraps values in single quotes when needed
- Escape embedded single quotes using '\'' idiom
- Update ExportPrefix to use ShellQuote
- Update BuildStartupCommand and PrependEnv in loader.go
- Add comprehensive tests for shell quoting edge cases

Backwards compatible: paths, hyphens, dots, and slashes are NOT quoted,
preserving existing agent behavior (GT_ROOT, BD_ACTOR, etc.).

This is a prerequisite for the OpenCode agent preset which uses
OPENCODE_PERMISSION='{"*":"allow"}' for auto-approve mode.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Subhrajit Makur
2026-01-22 05:19:39 +05:30
committed by GitHub
parent 87f9a7cfd1
commit 7a2090bb15
3 changed files with 143 additions and 4 deletions

View File

@@ -1256,7 +1256,7 @@ func BuildStartupCommand(envVars map[string]string, rigPath, prompt string) stri
// Build environment export prefix
var exports []string
for k, v := range resolvedEnv {
exports = append(exports, fmt.Sprintf("%s=%s", k, v))
exports = append(exports, fmt.Sprintf("%s=%s", k, ShellQuote(v)))
}
// Sort for deterministic output
@@ -1282,6 +1282,7 @@ func BuildStartupCommand(envVars map[string]string, rigPath, prompt string) stri
}
// PrependEnv prepends export statements to a command string.
// Values containing special characters are properly shell-quoted.
func PrependEnv(command string, envVars map[string]string) string {
if len(envVars) == 0 {
return command
@@ -1289,7 +1290,7 @@ func PrependEnv(command string, envVars map[string]string) string {
var exports []string
for k, v := range envVars {
exports = append(exports, fmt.Sprintf("%s=%s", k, v))
exports = append(exports, fmt.Sprintf("%s=%s", k, ShellQuote(v)))
}
sort.Strings(exports)
@@ -1365,7 +1366,7 @@ func BuildStartupCommandWithAgentOverride(envVars map[string]string, rigPath, pr
// Build environment export prefix
var exports []string
for k, v := range resolvedEnv {
exports = append(exports, fmt.Sprintf("%s=%s", k, v))
exports = append(exports, fmt.Sprintf("%s=%s", k, ShellQuote(v)))
}
sort.Strings(exports)