Repository navigation
Commit 1f9911d
authored
fix(shellwrap): quote arguments containing # so the login shell keeps them (#1756)
## Bug
Stdio upstreams are launched as `$SHELL -l -c "<joined command>"`
(`shellwrap.WrapWithUserShell`). Each argument goes through
`Shellescape`, but the POSIX branch only quotes when the argument
contains one of `" \t\n\r\"'\\$`;&|<>(){}[]?*~"`, and `#` is not in that
set. A word that begins with `#` starts a comment in `sh`/`bash`/`zsh
-c`, so the shell silently drops that argument and everything after it.
## Trigger
```json
{"name": "slack", "command": "npx", "args": ["-y", "slack-mcp", "#general", "--port", "3000"]}
```
The shell runs `npx -y slack-mcp`. `#general --port 3000` never reaches
the child.
## Fix
Add `#` to the POSIX special-character set, so such arguments are
single-quoted like every other metacharacter. The POSIX escaper copy in
`internal/oauth/spawnargv_round2_test.go` is updated to match, since
`TestPosixShellescape_MatchesProduction` pins the two together.
## Test
`TestShellescape_HashSurvivesShell` checks that `#general` is quoted,
then runs `sh -c "printf '%s\n' <escaped args>"` and asserts that all
four arguments (`#general --port 3000 a#b`) come back unchanged.
## Commands run
- `CGO_ENABLED=0 go test -count=1 ./internal/shellwrap`: ok
- `CGO_ENABLED=0 go test -count=1 ./internal/oauth`: ok
- `CGO_ENABLED=0 go test -count=1 -run 'Shell|Wrap|Escape|Docker'
./internal/upstream/core`: ok
- With the fix reverted (`git stash` of `shellwrap.go`), `-run
HashSurvives` fails: it expected `'#general'` but got `#general`, and
the shell output came back as `[""]`.
- `gofmt -l` on the edited files: no output1 parent a2ac978 commit 1f9911d
3 files changed
Lines changed: 31 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
76 | | - | |
| 76 | + | |
77 | 77 | | |
78 | 78 | | |
79 | 79 | | |
| |||
0 commit comments