Skip to content

Enforce agent tool context (authorizer/hooks/owner/in_cron) over the native MCP tool path #726

Description

@DROOdotFOO

Summary (research / low priority)

Native (vendor-owns-loop) backends -- handles_tools_internally? == true,
e.g. Backend.ClaudeCode / Backend.Cursor -- run their own tool loop and
execute Raxol Actions out-of-process over MCP (native_react/1 in
Raxol.Agent.Stream, tools injected via Harness.McpToolConfig). On that path
the framework cannot thread run context into tool execution:

  • context[:tool_authorizer] (the ToolPolicy that denies sensitive: true
    fund-mover Actions)
  • context[:tool_call_hooks] (the ToolCall.Hook pipeline)
  • app flags such as the cron :in_cron recursion guard and :owner scoping
    read by Actions.Cronjob

All of these are silently dropped, because the spawned MCP server that runs the
tool receives none of the caller's BEAM-process context. Any context-based
security control is therefore unenforced when a native backend is in use.

This does not bite today: no sensitive/context-guarded Action is wired
into any native react call, Actions.Cronjob is unwired everywhere, and there
is no MCP server that reads RAXOL_MCP_TOOLS_FILE to execute these tools. It is
a latent trap that springs the moment any of that is wired.

Interim mitigation already in place

Raxol.Agent.Scheduler.Fire fails closed for the cron fire path: when the
resolved backend is native (Stream.native_tool_loop?/1), it withholds
Actions.Cronjob from the injected toolset entirely (see PR from #494
follow-up). This is a point-fix scoped to cron fires.

What the general fix must cover

  1. Owner-scoping IDOR over the native path, not just the recursion guard.
    Even outside a fire (a normal interactive session on a native backend),
    cronjob list/remove would run without context[:owner] -> cross-owner
    read/delete. This is the same IDOR class the Cron scheduler: Raxol.Agent.Cron (parse-once, per-agent GenServer) #494 review caught on the
    framework path; the fix must reach the native path too.
  2. Generality -- replace the hardcoded Actions.Cronjob reference in
    Fire.guard_context_actions/2 with a declarative marker (an Action opting
    into "requires in-process context enforcement"), so authorizer/hooks/owner/
    in_cron-dependent Actions are withheld from any native toolset by
    construction, and a new such Action can't silently regress.
  3. Enforcement, not just withholding -- ideally carry a minimal, safe
    projection of context (owner, in_cron, authorizer verdicts) into the MCP
    tool config so the out-of-process server can reconstruct and enforce it,
    rather than dropping capability. This is the larger design question.

Scope

Research item -- design first (option 3 from the #494 follow-up triage). Low
priority: no live exposure until native tool derivation is actually wired for a
context-guarded Action. Tracks alongside #494.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions