POSIX safe mode has the same dynamic-construct bypass as the PowerShell one fixed in #37

Open
#44 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Quiet
Tech stack
python, shell
Domain
security

Research direction

Start by reviewing the POSIX safe-mode handling and SHELL_EXPANSION_RE, then compare the PowerShell change in #37 and the related discussion in #43. Decide explicitly whether to gate bare variables, narrow the check to command position, or document reliance on the sandbox; done means the chosen behavior and its impact on safe-mode usage are clear.

Written by the indexing model from the issue text.

Description

Problem

SHELL_EXPANSION_RE gates backticks, $(, and ${, but not a bare $var. Since the destructive and network scans match on literal command names, a name assembled at runtime slips past them:

c=cu'rl'; $c example.com          # NETWORK_RE never sees "curl"
f='-rf'; rm $f /some/path         # DESTRUCTIVE_RE never sees "rm -rf"

This is the POSIX twin of the PowerShell bypass fixed in #37 ($c='Invoke-WebRequest'; & $c example.com). It predates that PR — it's in main today — and the same reasoning applies: keyword scanning is only sound when the command text is literal, and a bare variable breaks that precondition.

Why it wasn't fixed alongside #37

The PowerShell gate was scoped to hosts where PowerShell is the interpreter precisely to avoid changing POSIX behavior in a contributor PR. Extending it to POSIX means echo $HOME starts requiring the shell_expansion permission in safe mode, which is a much more visible change — plenty of ordinary commands use variables.

Options

  1. Gate bare $ on POSIX too, consistent with #37. Most sound, most disruptive; needs a look at how often real safe-mode usage would start prompting.
  2. Gate only where it matters — a $ in command-name position (start of a segment, or after the call operator) rather than in argument position. Narrower blast radius, but "command position" needs a real parser to determine reliably, which is its own project (Codex uses tree-sitter for exactly this).
  3. Accept it and rely on the sandbox. On Linux, Landlock already contains the filesystem effects, and network is the main residual exposure — which #43 and the network-egress issue address more fundamentally.

Option 3 is the honest current state and argues for prioritizing sandbox/egress work over more scanner hardening. Worth deciding explicitly rather than leaving the gap undocumented.

Related: #37, #43.

Dominant language
Python
Stars
1.1k
Forks
190
Avg merge
1d 44m
Merged PRs (30d)
1

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from xyTom/coding-tools-mcp

All issues in xyTom/coding-tools-mcp

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.