Skip to content

Shell redirect targets bypass the external_directory permission #32628

Closed as not planned

Description

@warmjademe

When the shell tool scans a command for out-of-project paths, it gates them through the external_directory permission (default ask) — the same boundary the native write/edit/read tools enforce. But the scan skips redirection nodes (packages/opencode/src/tool/shell.ts: … || item.type === "redirection") continue), and there is no redirect-target handling. As a result a shell redirect target is never checked against external_directory:

  • cp foo /tmp/out → external_directory is asked ✅
  • cat foo > /tmp/out, env > /tmp/out, echo k >> ~/.ssh/authorized_keys → external_directory is never consulted; only the bash permission fires, and the redirect silently writes outside the project.

So a one-token shell redirect bypasses the project boundary that every other write path in opencode respects.

Reproduce (on current dev): with external_directory set to ask/deny, cp src /external/x prompts but env > /external/x does not, and the write to /external/x goes through.

Impact: an out-of-project write/exfiltration via redirection is not gated by external_directory, inconsistent with cp/mv/native tools.

A fix is proposed in the linked PR (feed file_redirect destinations through the existing argPath → containsPath → scan.dirs pipeline; skip fd-dups / here-docs / std-stream pseudo-devices).

Activity

  1. github-actions commented on Jun 17, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

  2. warmjademe commented on Jun 17, 2026

    @warmjademe
    Author

    Related to #31485, which proposes replacing tree-sitter-bash with a structural parser to fix this whole class of permission bypasses. This issue is one concrete instance of that class — shell redirect targets aren't checked against external_directory — and the linked PR is a small, targeted fix using the existing arg-scan pipeline. It stands on its own and doesn't depend on the larger parser rewrite, so I kept it separate rather than folding it into #31485.

  3. warmjademe commented on Jun 17, 2026

    @warmjademe
    Author

    Re #18396: that issue is the broader case where a bash subprocess writes outside permitted dirs as a side effect (e.g. python3 -m venv /home/user/venv). A forked process does its own I/O, so that can't be caught by parsing the command and is out of scope for this fix.

    This issue is the narrower, parseable slice: a shell redirect target (env > /outside, cat foo >> ~/.ssh/...) that opencode's own command scanner already inspects for path arguments but skips for redirections. The linked PR closes exactly that gap by routing redirect targets through the existing external_directory scan — it does not (and can't, at the parse layer) resolve the general subprocess-side-effect case in #18396. Keeping it separate so the PR's scope stays honest; happy to re-link to #18396 if a maintainer prefers tracking it there.

  4. github-actions commented on Aug 17, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions