Skip to content

fix(ai): tools inherit caller capabilities instead of ai.chat acting as a blanket read grant#51

Merged
DavidBabinec merged 7 commits into
mainfrom
fix/ai-tool-capability-gating
Jun 13, 2026
Merged

fix(ai): tools inherit caller capabilities instead of ai.chat acting as a blanket read grant#51
DavidBabinec merged 7 commits into
mainfrom
fix/ai-tool-capability-gating

Conversation

@DavidBabinec

Copy link
Copy Markdown
Contributor

What changed

Security hardening finding #1 (2026-06-12 audit): the AI chat toolset only filtered write tools by ai.tools.write — read tools were never capability-scoped, and executeAiTool dispatched handlers with no check. Any role granted ai.chat (the chat handler explicitly anticipates "a Client granted chat") could have the model call list_users (every email + role), get_document/list_documents/search_documents (any row, drafts included), and list_media (the whole library) — reads its own HTTP routes would refuse.

Now the agent inherits the caller's capabilities by construction:

  • AiTool.requiredCapabilities (ANY-OF) declares each tool's gate, mirroring its HTTP-route equivalent: list_usersusers.manage; document reads → the requireDataAccess six-cap set; list_mediamedia.read; collection/schema reads → data.tables.read|manage.
  • toolAllowedForCapabilities (server/ai/tools/capabilityGate.ts) is the single gate: mutatesai.tools.write, plus the ANY-OF requiredCapabilities.
  • selectToolsForScope filters the offered toolset through it (load-bearing: the tool loop only executes offered tools).
  • executeAiTool re-checks before dispatch — server and browser tools — as defence in depth. ToolContext/ToolContextBase now carry the caller's capability set.
  • Defence-in-depth breadth: content write tools mapped to their data-route gates (create/edit/publish/reassign); site tools mapped to the editor's structure/content/style change-class model; site snapshot reads → site.read.

Why

Pre-release roles ship with ai.chat only on Owner/Admin, but custom roles (which the AI feature invites operators to create) would otherwise turn ai.chat into a privilege escalation / email-enumeration / draft-exfiltration vector.

Impact

No behavior change for Owner/Admin (they hold every mapped capability). Restricted roles now see exactly the tools matching what they could do over HTTP.

Verification

  • bun run build — clean
  • bun test — 5386 pass / 0 fail (includes new src/__tests__/agent/aiToolCapabilityGate.test.ts: 13 cases across the helper, selection filtering, and dispatch re-check)
  • bun run lint — clean

🤖 Generated with Claude Code

DavidBabinec and others added 6 commits June 12, 2026 11:39
…olContext

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cope through it

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
list_users -> users.manage; list/get/search documents -> the requireDataAccess
six-cap set; collections/schema -> data.tables.read|manage; list_media -> media.read.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…caps

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Content write tools mirror their data-route gates (create/edit/publish/reassign);
site tools mirror the editor change-class model (structure/content/style, site.read
for snapshot reads). The executeAiTool re-check now covers browser tools too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…es gating

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 699ae9a1-229d-47df-a039-8d0065365d50

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ai-tool-capability-gating

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…y-gating

# Conflicts:
#	server/ai/runtime/types.ts
@DavidBabinec
DavidBabinec marked this pull request as ready for review June 13, 2026 07:23
@DavidBabinec
DavidBabinec merged commit 057d736 into main Jun 13, 2026
@DavidBabinec
DavidBabinec deleted the fix/ai-tool-capability-gating branch June 13, 2026 09:21
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.

1 participant