security(mitmproxy): use shlex.quote for sandcat.env generation - #101
Open
shejnowicz wants to merge 5 commits into
Open
security(mitmproxy): use shlex.quote for sandcat.env generation#101shejnowicz wants to merge 5 commits into
shejnowicz wants to merge 5 commits into
Conversation
Replace the hand-rolled _shell_escape with stdlib shlex.quote when generating sandcat.env. Fixes silent newline corruption (\n is not an escape inside shell double quotes), closes the interactive-shell `!` history-expansion edge, and removes a hand-maintained escaping table. Values flow from settings.json AND secret vaults, so robust quoting is defense-in-depth. Two tasks: code+unit tests, hands-on container verification of bit-perfect hostile-value delivery. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DFCiFbv1Cpr7yzCU8ftvzZ
review) shlex.quote preserves literal newlines in values, so a multi-line value's continuation line could itself match app-init.sh's `^export ` grep, producing a phantom var count and printing a fragment of the value to the startup log. The addon now writes an authoritative `# names: ...` header (built only from validated, whitespace-free names) as the first line of sandcat.env, and app-init.sh parses that header instead of grepping export lines. Falls back to a count-only message (no grep) if the header is absent, for old-addon/new-init-script transitions.
…v format Rename TestShellEscaping (and its test_*_escaped methods) to TestEnvValueQuoting / test_*_preserved_via_quoting — shlex.quote quotes values, it doesn't escape them, and the old names described behavior that no longer exists. Add coverage for the new sandcat.env header (names-only, no value fragments — including from a hostile multi-line value) and for the empty-string value case. Update README's sandcat.env format example from the old escaped-double-quote style to the shlex.quote reality.
Per repo convention, SDD spec/plan docs live in the working session, not the PR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #19.
Summary
Replaces the hand-rolled `_shell_escape` in `mitmproxy_addon_common.py` with stdlib `shlex.quote` when generating `sandcat.env` (the file `app-init.sh` sources to export env vars and secret placeholders into the agent container).
What this actually fixes (honest framing — this is robustness hardening, not an active-exploit fix; the old escaper did cover `\`, `"`, `$`, `
``):Note: secret VALUES never land in `sandcat.env` — only `SANDCAT_PLACEHOLDER_*` strings do (built from regex-validated names, always shlex-safe). The variable-content path is the user-authored `env` block in settings.json.
Follow-up fix found in review
Preserving newlines made a latent consumer bug reachable: `app-init.sh`'s startup log counted and listed env vars by grepping `^export ` lines — a multi-line value's continuation line could phantom-match and print a value fragment into the log. Fixed by having the addon emit an authoritative names-only header as the first line of `sandcat.env` (`# names: A B C`, safe by construction — names are regex-validated), which `app-init.sh` now reads instead. The no-header fallback prints a nameless summary; it does NOT fall back to the value-leaking grep.
Format change
```
names: GIT_USER_NAME ANTHROPIC_API_KEY
export GIT_USER_NAME='Alice Example' # single-quoted when needed
export ANTHROPIC_API_KEY=SANDCAT_PLACEHOLDER_ANTHROPIC_API_KEY # bare when shlex-safe
```
Consumers audited: the only readers are shell `source` sites (`app-init.sh`, the `/etc/profile.d/sandcat-env.sh` copy, `su - vscode -c`) plus the now-fixed log summary. No other parser exists in scripts, bats, or compose.
Test plan
🤖 Generated with Claude Code
https://claude.ai/code/session_01DFCiFbv1Cpr7yzCU8ftvzZ