# Reject shell substitutions in terminal tool commands \(\#51689\) · gitcafe/zed

[View on GitCafe](https://git.cafe/gitcafe/zed/commit/f3fb4e04aa85dbbde6e83d28f231fc452cd8863f)

Repository: [gitcafe/zed](https://git.cafe/gitcafe/zed)

Visibility: public

Requested revision: f3fb4e04aa85dbbde6e83d28f231fc452cd8863f

Requested commit: f3fb4e04aa85dbbde6e83d28f231fc452cd8863f

Commit: f3fb4e04aa85dbbde6e83d28f231fc452cd8863f

Tree: 1a0362dfbe05612f3b19eba85b3954e83100b5b5

Author: Richard Feldman

Committer: GitHub

## Message

```
Reject shell substitutions in terminal tool commands (#51689)

Harden the terminal tool's permission system to reject commands
containing shell substitutions and interpolations (`$VAR`, `${VAR}`,
`$(…)`, backticks, `$((…))`, `<(…)`, `>(…)`) before they reach terminal
creation.

## Changes

### Shell command parser (`shell_command_parser`)
- Added structured terminal command-prefix extraction with env-var
prefix support
- Added parser-backed validation that classifies commands as
Safe/Unsafe/Unknown
- Extended normalized command extraction to include scalar env-var
assignments in order
- Preserved quoted assignment values when they contain whitespace or
special characters

### Pattern extraction (`agent/pattern_extraction`)
- Updated terminal pattern extraction to use structured parser output
- Included env-var prefixes in generated allow patterns
- Normalized regex token boundaries to `\s+` while preserving display
whitespace

### Tool permissions (`agent/tool_permissions`)
- Added invalid-terminal-command rejection for forbidden
substitutions/interpolations
- Added unconditional allow-all bypass (global default Allow, or
terminal-specific Allow with empty patterns)
- Preserved hardcoded denial precedence over allow-all

### Terminal tool (`agent/tools/terminal_tool`)
- Updated tool description and input schema to explicitly prohibit shell
substitutions
- Added comprehensive SEC-264 regression test suite (20 new tests)
covering:
- All forbidden constructs (`${HOME}`, `$1`, `$?`, `$$`, `$@`,
`$(whoami)`, backticks, `$((1+1))`, `<(ls)`, `>(cat)`, env-prefix
variants, multiline, nested)
  - Allow-all exception paths (global and terminal-specific)
  - Hardcoded-denial precedence
- Env-prefix permission flow (matching, value mismatch rejection,
multiple assignments, quoted whitespace)

Closes SEC-264

Release Notes:

- Terminal tool permissions regexes can now match environment variables
(e.g. `FOO=bar cmd arg1 arg2`)
- If terminal tool permissions have active permissions regexes running
on them, then bare interpolations like `$FOO` are disallowed for
security, since regexes wouldn't be able to match on them.
```

## Parents

- [977cd6ac7e18ae0d0c4d528bb6bb1e987fd7b9d0](https://git.cafe/gitcafe/zed/commit/977cd6ac7e18ae0d0c4d528bb6bb1e987fd7b9d0?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zed/tree/f3fb4e04aa85dbbde6e83d28f231fc452cd8863f?format=markdown)
