[FEATURE]: Extract inner commands from xargs/parallel/find -exec for permission matching #6868

Open
opened 2026-02-16 18:05:28 -05:00 by yindo · 3 comments
Owner

Originally created by @rcdailey on GitHub (Jan 19, 2026).

Originally assigned to: @thdxr on GitHub.

Problem

When a command is wrapped in xargs, find -exec, parallel, watch, or similar command wrappers, the permission system only sees the wrapper command, not the inner command being executed.

For example, with this permission config:

"bash": {
  "*": "allow",
  "gh api* -X DELETE*": "ask"
}

This command bypasses the permission check entirely:

gh api repos/owner/repo/code-scanning/analyses --paginate -q '.[] | .id' | xargs -I{} gh api -X DELETE repos/owner/repo/code-scanning/analyses/{}

The bash tool parses this as two commands via tree-sitter:

  1. gh api repos/... --paginate -q '...' - matches *: allow
  2. xargs -I{} gh api -X DELETE ... - starts with xargs, not gh api, so matches *: allow

The dangerous gh api -X DELETE is never checked because it appears as arguments to xargs, not as a standalone command.

Proposed Solution

The bash tool could recognize common command wrappers and extract their inner commands for permission checking:

  • xargs [-I...] <command> - extract command after flags
  • find ... -exec <command> \; or -exec <command> + - extract command between -exec and terminator
  • parallel <command> - extract command
  • watch [-n...] <command> - extract command after flags
  • env [VAR=val...] <command> - extract command after env vars

When a wrapper is detected, both the wrapper invocation AND the inner command should be checked against permission rules.

Workaround

Users can currently work around this by adding a leading * to patterns:

"*gh api* -X DELETE*": "ask"

This matches the pattern anywhere in the command string, but it's non-obvious and easy to miss.

Originally created by @rcdailey on GitHub (Jan 19, 2026). Originally assigned to: @thdxr on GitHub. ### Problem When a command is wrapped in `xargs`, `find -exec`, `parallel`, `watch`, or similar command wrappers, the permission system only sees the wrapper command, not the inner command being executed. For example, with this permission config: ```json "bash": { "*": "allow", "gh api* -X DELETE*": "ask" } ``` This command bypasses the permission check entirely: ```bash gh api repos/owner/repo/code-scanning/analyses --paginate -q '.[] | .id' | xargs -I{} gh api -X DELETE repos/owner/repo/code-scanning/analyses/{} ``` The bash tool parses this as two commands via tree-sitter: 1. `gh api repos/... --paginate -q '...'` - matches `*`: allow 2. `xargs -I{} gh api -X DELETE ...` - starts with `xargs`, not `gh api`, so matches `*`: allow The dangerous `gh api -X DELETE` is never checked because it appears as arguments to `xargs`, not as a standalone command. ### Proposed Solution The bash tool could recognize common command wrappers and extract their inner commands for permission checking: - `xargs [-I...] <command>` - extract command after flags - `find ... -exec <command> \;` or `-exec <command> +` - extract command between -exec and terminator - `parallel <command>` - extract command - `watch [-n...] <command>` - extract command after flags - `env [VAR=val...] <command>` - extract command after env vars When a wrapper is detected, both the wrapper invocation AND the inner command should be checked against permission rules. ### Workaround Users can currently work around this by adding a leading `*` to patterns: ```json "*gh api* -X DELETE*": "ask" ``` This matches the pattern anywhere in the command string, but it's non-obvious and easy to miss.
Author
Owner

@github-actions[bot] commented on GitHub (Jan 19, 2026):

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

  • #8936: Bash: Default permission is "allow" - Related to permission system defaults
  • #8832: opencode not respecting permissions - Similar permission enforcement issue
  • #9511: [FEATURE]: Hierarchical rules triggered by file-related tool calls - Related to permission rule matching for files
  • #9390: [BUG] a is not accepted as always accept permission - Related to permission system bugs

Feel free to ignore if none of these address your specific case.

@github-actions[bot] commented on GitHub (Jan 19, 2026): This issue might be a duplicate of existing issues. Please check: - #8936: Bash: Default permission is "allow" - Related to permission system defaults - #8832: opencode not respecting permissions - Similar permission enforcement issue - #9511: [FEATURE]: Hierarchical rules triggered by file-related tool calls - Related to permission rule matching for files - #9390: [BUG] `a` is not accepted as always accept permission - Related to permission system bugs Feel free to ignore if none of these address your specific case.
Author
Owner

@HeySora commented on GitHub (Feb 6, 2026):

I will also add that awk can do system calls too, through something like awk '{system("<command>")}'

@HeySora commented on GitHub (Feb 6, 2026): I will also add that `awk` can do system calls too, through something like `awk '{system("<command>")}'`
Author
Owner

@aspiers commented on GitHub (Feb 16, 2026):

And perl / python / ruby / node ... in fact pretty much any language interpreter will allow that! If your default policy is allow then all bets are off and you will need some other form of protection e.g. kernel-level sandboxing.

@aspiers commented on GitHub (Feb 16, 2026): And `perl` / `python` / `ruby` / `node` ... in fact pretty much any language interpreter will allow that! If your default policy is allow then all bets are off and you will need some other form of protection e.g. kernel-level sandboxing.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#6868