Skip to content

fix(security): restrict subagent toolsets to parent's enabled set - #3188

Closed
dieutx wants to merge 1 commit into
NousResearch:mainfrom
dieutx:fix/delegate-toolset-privilege-escalation
Closed

fix(security): restrict subagent toolsets to parent's enabled set#3188
dieutx wants to merge 1 commit into
NousResearch:mainfrom
dieutx:fix/delegate-toolset-privilege-escalation

Conversation

@dieutx

@dieutx dieutx commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Summary

The delegate_task tool lets the LLM request arbitrary toolsets for subagents, including ones the user explicitly disabled for the parent. A model calling delegate_task(toolsets=["terminal", "file", "web", "browser"]) when the parent only has ["terminal", "file"] grants the subagent web and browser — a privilege escalation.

Root Cause

_build_child_agent() at delegate_tool.py:177 passes LLM-provided toolsets through _strip_blocked_tools (which removes delegation, clarify, memory, code_execution) but never intersects with the parent's enabled_toolsets. The blocked-tool filter is a different, smaller set than the user's tool restrictions.

Fix

Intersect before filtering (tools/delegate_tool.py)

parent_toolsets = set(getattr(parent_agent, "enabled_toolsets", None) or DEFAULT_TOOLSETS)
if toolsets:
    child_toolsets = _strip_blocked_tools([t for t in toolsets if t in parent_toolsets])

The no-toolsets path (child inherits parent's full set) and the blocked-tools filter are both unchanged.

Tests

5 new tests: intersection drops extras, subset passes through, no-toolsets inherits parent, blocked tools still removed, empty intersection yields empty set.

5 passed

The delegate_task tool accepts a toolsets parameter directly from the
LLM's function call arguments. When provided, these toolsets are passed
through _strip_blocked_tools but never intersected with the parent
agent's enabled_toolsets. A model can request toolsets the parent does
not have (e.g., web, browser, rl), granting the subagent tools that
were explicitly disabled for the parent.

Intersect LLM-requested toolsets with the parent's enabled set before
applying the blocked-tool filter, so subagents can only receive a
subset of the parent's tools.
@teknium1

Copy link
Copy Markdown
Contributor

Merged via PR #3269. Your commit was cherry-picked onto current main with original authorship preserved. Good catch on the privilege escalation — subagent toolsets are now intersected with the parent's enabled set before filtering. Thanks!

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