-
Notifications
You must be signed in to change notification settings - Fork 373
docs: document Claude bypassPermissions/--allowed-tools security boundary #28174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -679,6 +679,25 @@ When developing a new command: | |||||
| ### Go Code Style | ||||||
| - **ALWAYS use `any` instead of `interface{}`** - Use the modern `any` type alias (Go 1.18+) for consistency across the codebase | ||||||
|
|
||||||
| ### Claude Engine Tool Enforcement Security Model | ||||||
|
|
||||||
| When adding code to `pkg/workflow/claude_engine.go` or `pkg/workflow/claude_tools.go`, be aware of how Claude's permission mode affects tool enforcement: | ||||||
|
|
||||||
| **Two permission modes are used at runtime:** | ||||||
|
|
||||||
| 1. **`acceptEdits` (default)** — Claude Code honors `--allowed-tools` as the effective tool boundary. Workflow `tools:` and `mcp-servers: allowed:` restrictions are enforced client-side. | ||||||
|
|
||||||
| 2. **`bypassPermissions`** — Claude Code silently ignores `--allowed-tools`. Every tool exposed by the MCP gateway is reachable regardless of the workflow's declared tool configuration. This mode is only used when the workflow grants unrestricted bash access (e.g., `bash: "*"`, `bash: [":*"]`, or `bash: null`). | ||||||
|
||||||
| 2. **`bypassPermissions`** — Claude Code silently ignores `--allowed-tools`. Every tool exposed by the MCP gateway is reachable regardless of the workflow's declared tool configuration. This mode is only used when the workflow grants unrestricted bash access (e.g., `bash: "*"`, `bash: [":*"]`, or `bash: null`). | |
| 2. **`bypassPermissions`** — Claude Code silently ignores `--allowed-tools`. Every tool exposed by the MCP gateway is reachable regardless of the workflow's declared tool configuration. This mode is only used when the workflow grants unrestricted bash access (e.g., `bash: true`, `bash: "*"`, `bash: [":*"]`, or `bash: null`). |
Copilot
AI
Apr 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The converter referenced here appears to be outdated/misnamed: the workflow gateway conversion for Claude is implemented in actions/setup/js/convert_gateway_config_claude.cjs (and invoked by actions/setup/sh/start_mcp_gateway.sh), not convert_gateway_config_claude.sh. Consider updating this bullet to point at the .cjs converter (or explicitly mention both, if both are still supported), so contributors look at the code path that actually runs in CI.
| - `convert_gateway_config_claude.sh` preserves the `tools` field from gateway output — this is what enforces restrictions in `bypassPermissions` mode | |
| - `actions/setup/js/convert_gateway_config_claude.cjs` (invoked by `actions/setup/sh/start_mcp_gateway.sh`) preserves the `tools` field from gateway output — this is what enforces restrictions in `bypassPermissions` mode |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -139,6 +139,11 @@ mcp-servers: | |||||
| allowed: ["search_pages", "get_page"] # or ["*"] to allow all | ||||||
| ``` | ||||||
|
|
||||||
| The `allowed:` filter is enforced at the **MCP gateway level** — the gateway only exposes the listed tools to the agent. This enforcement applies regardless of which AI engine or permission mode is in use. | ||||||
|
|
||||||
| > [!IMPORTANT] | ||||||
| > For Claude workflows that grant unrestricted bash access (`bash: "*"` or `bash: [":*"]`), Claude runs in `bypassPermissions` mode and its `--allowed-tools` flag is silently ignored. In that case, the `allowed:` gateway filter is the **sole effective tool boundary**. Always specify `allowed:` on each `mcp-servers:` entry when tool restrictions matter. See [Claude Tool Enforcement Security Model](/gh-aw/reference/engines/#claude-tool-enforcement-security-model) for details. | ||||||
|
||||||
| > For Claude workflows that grant unrestricted bash access (`bash: "*"` or `bash: [":*"]`), Claude runs in `bypassPermissions` mode and its `--allowed-tools` flag is silently ignored. In that case, the `allowed:` gateway filter is the **sole effective tool boundary**. Always specify `allowed:` on each `mcp-servers:` entry when tool restrictions matter. See [Claude Tool Enforcement Security Model](/gh-aw/reference/engines/#claude-tool-enforcement-security-model) for details. | |
| > For Claude workflows that grant unrestricted bash access (`bash: "*"` or `bash: [":*"]`, as well as equivalent allow-all forms like `bash: true` and `bash: null`), Claude runs in `bypassPermissions` mode and its `--allowed-tools` flag is silently ignored. In that case, the `allowed:` gateway filter is the **sole effective tool boundary**. Always specify `allowed:` on each `mcp-servers:` entry when tool restrictions matter. See [Claude Tool Enforcement Security Model](/gh-aw/reference/engines/#claude-tool-enforcement-security-model) for details. |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -339,6 +339,41 @@ timeout-minutes: 60 | |||||
| | `max-turns` | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | Iteration budget (Claude only) | | ||||||
| | `max-continuations` | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | Autopilot run budget (Copilot only) | | ||||||
|
|
||||||
| ## Claude Tool Enforcement Security Model | ||||||
|
|
||||||
| Claude Code uses one of two permission modes at runtime, and which mode is selected determines whether the declared `tools:` allowlist is enforced: | ||||||
|
|
||||||
| ### `acceptEdits` mode (default) | ||||||
|
|
||||||
| By default, gh-aw starts Claude Code with `--permission-mode acceptEdits`. In this mode, Claude honors the `--allowed-tools` flag. The workflow's declared `tools:` and `mcp-servers: allowed:` configuration is compiled into an explicit allowlist and passed to the Claude CLI. Only the tools listed there are accessible to the agent. | ||||||
|
|
||||||
| ### `bypassPermissions` mode (unrestricted bash) | ||||||
|
|
||||||
| When the workflow grants unrestricted bash access — `bash: "*"`, `bash: [":*"]`, or `bash: null` — gh-aw switches to `--permission-mode bypassPermissions`. **In this mode, Claude Code silently ignores `--allowed-tools`.** Every tool exposed by the MCP gateway is reachable regardless of the workflow's declared tool configuration. | ||||||
|
|
||||||
|
Comment on lines
+350
to
+353
|
||||||
| > [!WARNING] | ||||||
| > Do not rely on `tools:` or `mcp-servers: allowed:` for security guarantees when unrestricted bash is granted. In `bypassPermissions` mode, the agent can already run arbitrary shell commands, so `--allowed-tools` provides no meaningful additional boundary. | ||||||
|
||||||
| > Do not rely on `tools:` or `mcp-servers: allowed:` for security guarantees when unrestricted bash is granted. In `bypassPermissions` mode, the agent can already run arbitrary shell commands, so `--allowed-tools` provides no meaningful additional boundary. | |
| > Do not rely on Claude-side `tools:` / `--allowed-tools` enforcement for security guarantees when unrestricted bash is granted. In `bypassPermissions` mode, the agent can already run arbitrary shell commands, so the Claude CLI allowlist provides no meaningful additional boundary. However, `mcp-servers: allowed:` remains enforced by the MCP gateway for MCP tools and is still the effective boundary there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In
acceptEditsmode,--allowed-toolsis enforced client-side by Claude, butmcp-servers: allowed:is enforced gateway-side (server-side), not client-side. The current wording implies bothtools:andmcp-servers: allowed:are client-side restrictions, which is inaccurate and could confuse contributors making security-sensitive changes.