You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: AGENTS.md
+19Lines changed: 19 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -679,6 +679,25 @@ When developing a new command:
679
679
### Go Code Style
680
680
-**ALWAYS use `any` instead of `interface{}`** - Use the modern `any` type alias (Go 1.18+) for consistency across the codebase
681
681
682
+
### Claude Engine Tool Enforcement Security Model
683
+
684
+
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:
685
+
686
+
**Two permission modes are used at runtime:**
687
+
688
+
1.**`acceptEdits` (default)** — Claude Code honors `--allowed-tools` as the effective tool boundary. Workflow `tools:` and `mcp-servers: allowed:` restrictions are enforced client-side.
689
+
690
+
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`).
691
+
692
+
**Security boundary in `bypassPermissions` mode:**
693
+
When `bypassPermissions` is active, the **MCP gateway `allowed:` filter is the sole effective tool boundary**. The compiled `tools` field in the gateway configuration (`/tmp/gh-aw/mcp-config/mcp-servers.json`) controls which tools each MCP server exposes. Gateway-side enforcement applies regardless of what the agent requests.
694
+
695
+
**Implication for code changes:**
696
+
-`hasBashWildcardInTools()` in `claude_tools.go` determines which mode is selected — changes here affect the security boundary
697
+
-`computeAllowedClaudeToolsString()` builds the `--allowed-tools` string — only effective in `acceptEdits` mode
698
+
-`convert_gateway_config_claude.sh` preserves the `tools` field from gateway output — this is what enforces restrictions in `bypassPermissions` mode
699
+
- Do not remove or weaken either enforcement layer; they complement each other for different access scenarios
700
+
682
701
### Channel Lifecycle Guidelines
683
702
684
703
Go channels require explicit lifecycle management to prevent goroutine leaks and resource exhaustion. Follow these guidelines when working with channels:
Copy file name to clipboardExpand all lines: docs/src/content/docs/guides/mcps.md
+5Lines changed: 5 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -139,6 +139,11 @@ mcp-servers:
139
139
allowed: ["search_pages", "get_page"] # or ["*"] to allow all
140
140
```
141
141
142
+
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.
143
+
144
+
> [!IMPORTANT]
145
+
> 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.
146
+
142
147
## Shared MCP Configurations
143
148
144
149
Pre-configured MCP server specifications are available in [`.github/workflows/shared/mcp/`](https://github.com/github/gh-aw/tree/main/.github/workflows/shared/mcp) and can be copied or imported directly. Examples include:
Claude Code uses one of two permission modes at runtime, and which mode is selected determines whether the declared `tools:` allowlist is enforced:
345
+
346
+
### `acceptEdits` mode (default)
347
+
348
+
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.
349
+
350
+
### `bypassPermissions` mode (unrestricted bash)
351
+
352
+
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.
353
+
354
+
> [!WARNING]
355
+
> 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.
356
+
357
+
### Gateway-side enforcement
358
+
359
+
The **MCP gateway's `allowed:` filter is the sole effective tool boundary in `bypassPermissions` mode** (and a second layer of enforcement in `acceptEdits` mode). gh-aw compiles the `allowed:` list from each `mcp-servers:` entry into the gateway configuration before the agent starts. The gateway enforces this list server-side, regardless of what the agent requests.
360
+
361
+
```yaml wrap
362
+
mcp-servers:
363
+
notion:
364
+
container: "mcp/notion"
365
+
allowed: ["search_pages", "get_page"] # enforced at gateway level
For workflows that must restrict which MCP tools are accessible, always specify `allowed:` on each `mcp-servers:` entry. This applies regardless of whether unrestricted bash is used.
0 commit comments