Commit 2f0ff5f
fix(sdk): prevent shell injection in MCP config via proper escaping (#1276)
## Summary
Fixes #1154
When creating a sandbox with an `mcp` config, the JSON-serialized config
is interpolated directly into a shell command wrapped in single quotes.
Since `json.dumps()` / `JSON.stringify()` do not escape single quotes,
any MCP config value containing a single quote (e.g., API keys, tokens,
URLs) breaks out of shell quoting and allows arbitrary command execution
inside the sandbox.
## Changes
### Python SDK (`sandbox_async/main.py`, `sandbox_sync/main.py`)
- Use `shlex.quote()` to properly escape the JSON config string (4
locations)
- `shlex.quote()` is a stdlib function designed exactly for this purpose
### JS/TS SDK (`sandbox/index.ts`)
- Add a `shellQuote()` helper that escapes single quotes using the
standard `'\'''` pattern (equivalent to Python's `shlex.quote()`)
- Apply it to both MCP config interpolation sites (2 locations)
## Before / After
**Before** (vulnerable):
```
mcp-gateway --config '{"servers": {"test": {"envs": {"KEY": "it's a value"}}}}'
# ^^ breaks out
```
**After** (safe):
```
mcp-gateway --config '{"servers": {"test": {"envs": {"KEY": "it'\''s a value"}}}}'
# ^^^^ properly escaped
```
## Testing
Verified escaping behavior for both Python (`shlex.quote`) and JS
(`shellQuote`) with the PoC from the issue — single quotes in config
values are properly escaped and no longer allow shell breakout.
---------
Co-authored-by: Mish Ushakov <10400064+mishushakov@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>1 parent 7695889 commit 2f0ff5f
5 files changed
Lines changed: 23 additions & 6 deletions
File tree
- .changeset
- packages
- js-sdk/src
- sandbox
- python-sdk/e2b
- sandbox_async
- sandbox_sync
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
| |||
301 | 302 | | |
302 | 303 | | |
303 | 304 | | |
304 | | - | |
| 305 | + | |
305 | 306 | | |
306 | 307 | | |
307 | 308 | | |
| |||
398 | 399 | | |
399 | 400 | | |
400 | 401 | | |
401 | | - | |
| 402 | + | |
402 | 403 | | |
403 | 404 | | |
404 | 405 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
125 | 125 | | |
126 | 126 | | |
127 | 127 | | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
128 | 136 | | |
129 | 137 | | |
130 | 138 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
235 | 236 | | |
236 | 237 | | |
237 | 238 | | |
238 | | - | |
| 239 | + | |
239 | 240 | | |
240 | 241 | | |
241 | 242 | | |
| |||
616 | 617 | | |
617 | 618 | | |
618 | 619 | | |
619 | | - | |
| 620 | + | |
620 | 621 | | |
621 | 622 | | |
622 | 623 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
233 | 234 | | |
234 | 235 | | |
235 | 236 | | |
236 | | - | |
| 237 | + | |
237 | 238 | | |
238 | 239 | | |
239 | 240 | | |
| |||
617 | 618 | | |
618 | 619 | | |
619 | 620 | | |
620 | | - | |
| 621 | + | |
621 | 622 | | |
622 | 623 | | |
623 | 624 | | |
| |||
0 commit comments