Skip to content

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

@rcdailey

Description

@rcdailey

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions