Skip to content

Add regex-based permissions system for tool execution control#22

Merged
chinmaymk merged 3 commits intomainfrom
claude/permissions-model-design-JmZQU
Mar 11, 2026
Merged

Add regex-based permissions system for tool execution control#22
chinmaymk merged 3 commits intomainfrom
claude/permissions-model-design-JmZQU

Conversation

@chinmaymk
Copy link
Copy Markdown
Owner

Summary

Adds a comprehensive permissions middleware that controls what tools can do through regex-based allow/deny rules per tool and per field. This enables fine-grained security policies without stopping the agent loop — denied calls return clear error messages so the model can adjust its approach.

Key Changes

  • New permissions middleware (src/agent/permissions.ts): Implements createPermissionsMiddleware() that evaluates tool calls against configurable regex rules. Deny patterns take priority over allow patterns.

  • Configuration types (src/config/types.ts): Added PermissionsConfig, PermissionRule, and PermissionFieldRule interfaces supporting:

    • no_rules: Bypass all checks
    • default_action: Control behavior for tools with no rules (allow or deny)
    • rules: Array of per-tool field constraints
  • Loop integration (src/agent/loop.ts): Modified AgentLoop to:

    • Add deny() callback and denied property to ToolExecutionContext
    • Capture denied tool calls and convert them to error results in the message stream
    • Allow the loop to continue after denial (no early termination)
  • Type updates (src/agent/types.ts): Extended ToolExecutionContext with deny() method and denied property for permission enforcement.

  • Configuration defaults (src/config/defaults.ts): Added empty permissions: {} to default config.

  • Main entry point (src/index.ts): Integrated permissions middleware into the agent loop's beforeToolExecution chain.

  • Comprehensive test suite (tests/agent/permissions.test.ts): 389 lines covering:

    • Allow/deny rule evaluation and priority
    • Multiple rules per tool
    • Field-specific constraints (command, path, content, url, etc.)
    • Default action behavior
    • Loop integration ensuring denied tools don't execute
  • Documentation (docs/site/permissions/index.md): Full guide with examples for common use cases (safe git commands, file restrictions, secret blocking, network lockdown).

Implementation Details

  • Deny priority: Deny patterns are checked first; if any match, the call is immediately rejected regardless of allow rules
  • Field-level granularity: Rules target specific input fields (e.g., command for bash, path for file tools, url for web_fetch)
  • Clear error messages: Denied calls include which rule was triggered, helping the model understand and adjust
  • Non-blocking: Denied tool calls become error results in the message stream; the loop continues and the model can retry with different parameters
  • Regex-based: All patterns are JavaScript RegExp strings, enabling flexible matching (anchors, character classes, etc.)

https://claude.ai/code/session_01WHxQAWvZarjgufPCxHhsHs

claude added 3 commits March 11, 2026 21:01
Implements per-tool, per-field allow/deny regex rules that control what
tools can do. Deny always takes priority over allow. Denied tool calls
return clear error messages to the model so it can adjust its approach.

Key changes:
- Add deny() to ToolExecutionContext so middleware can reject individual
  tool calls without killing the loop
- Add PermissionsConfig type with no_rules, default_action, and rules
- Built-in permissions middleware on beforeToolExecution hook
- 21 tests covering deny, allow, priority, field rules, and loop integration
- Documentation in README, docs/site/permissions, and configuration reference

https://claude.ai/code/session_01WHxQAWvZarjgufPCxHhsHs
- permissions.ts: 132 → 50 lines — inline field evaluation, remove
  separate helpers and discriminated union return type
- types.ts: remove redundant `denied` field from ToolExecutionContext,
  loop uses closure directly
- tests: flatten describe nesting, deduplicate config objects, 390 → 207 lines

https://claude.ai/code/session_01WHxQAWvZarjgufPCxHhsHs
@chinmaymk chinmaymk merged commit b14bf7c into main Mar 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants