fix(sandbox): create per-subagent ExecTool to avoid leaking allowPatterns
The shared ExecTool instance (sm.execTool) was mutated by SetAllowPatterns when spawning subagents, which leaked sandbox restrictions to the conductor. Basic commands like pwd and ls were blocked on the main agent after any subagent spawned with a preset. Create a new ExecTool per subagent instead of sharing a single instance. Remove the now-unused execTool field from SubagentManager. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3817aad8cf
commit
73560dbf66
1 changed files with 12 additions and 11 deletions
|
|
@ -3,7 +3,6 @@ package tools
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -33,7 +32,6 @@ type SubagentManager struct {
|
||||||
workspace string
|
workspace string
|
||||||
tools *ToolRegistry
|
tools *ToolRegistry
|
||||||
webSearchOpts WebSearchToolOptions
|
webSearchOpts WebSearchToolOptions
|
||||||
execTool *ExecTool // Shared exec tool for all presets
|
|
||||||
maxIterations int
|
maxIterations int
|
||||||
maxTokens int
|
maxTokens int
|
||||||
temperature float64
|
temperature float64
|
||||||
|
|
@ -53,11 +51,6 @@ func NewSubagentManager(
|
||||||
if reporter == nil {
|
if reporter == nil {
|
||||||
reporter = orch.Noop
|
reporter = orch.Noop
|
||||||
}
|
}
|
||||||
// Create a shared exec tool for all presets
|
|
||||||
execTool, err := NewExecTool(workspace, true)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("subagent: failed to create exec tool: %v (exec disabled for subagents)", err)
|
|
||||||
}
|
|
||||||
return &SubagentManager{
|
return &SubagentManager{
|
||||||
tasks: make(map[string]*SubagentTask),
|
tasks: make(map[string]*SubagentTask),
|
||||||
provider: provider,
|
provider: provider,
|
||||||
|
|
@ -66,7 +59,6 @@ func NewSubagentManager(
|
||||||
workspace: workspace,
|
workspace: workspace,
|
||||||
tools: NewToolRegistry(),
|
tools: NewToolRegistry(),
|
||||||
webSearchOpts: webSearchOpts,
|
webSearchOpts: webSearchOpts,
|
||||||
execTool: execTool,
|
|
||||||
maxIterations: 10,
|
maxIterations: 10,
|
||||||
nextID: 1,
|
nextID: 1,
|
||||||
reporter: reporter,
|
reporter: reporter,
|
||||||
|
|
@ -306,10 +298,19 @@ func (sm *SubagentManager) buildPresetRegistry(preset Preset, writeRoot string)
|
||||||
registry.Register(NewAppendFileTool(writeRoot, true))
|
registry.Register(NewAppendFileTool(writeRoot, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register exec and bg_monitor if allowed
|
// Register exec and bg_monitor if allowed.
|
||||||
|
// Each subagent gets its own ExecTool to avoid mutating the shared instance's
|
||||||
|
// allowPatterns (which would leak sandbox restrictions to the conductor).
|
||||||
if config.AllowedTools["exec"] {
|
if config.AllowedTools["exec"] {
|
||||||
// Use the shared exec tool but set allow patterns
|
execWorkDir := writeRoot
|
||||||
execTool := sm.execTool
|
if execWorkDir == "" {
|
||||||
|
execWorkDir = sm.workspace
|
||||||
|
}
|
||||||
|
execTool, err := NewExecTool(execWorkDir, true)
|
||||||
|
if err != nil {
|
||||||
|
// exec disabled for this subagent; skip registration
|
||||||
|
return registry
|
||||||
|
}
|
||||||
if config.ExecPolicy != nil {
|
if config.ExecPolicy != nil {
|
||||||
_ = execTool.SetAllowPatterns([]string{config.ExecPolicy.AllowPattern})
|
_ = execTool.SetAllowPatterns([]string{config.ExecPolicy.AllowPattern})
|
||||||
execTool.SetLocalNetOnly(config.ExecPolicy.LocalNetOnly)
|
execTool.SetLocalNetOnly(config.ExecPolicy.LocalNetOnly)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue