callPromotedTool: run tool scripts through sandbox instead of exec directly
This commit is contained in:
parent
e3a9ff4bf3
commit
9ea56242c3
|
|
@ -273,7 +273,7 @@ func (e *Server) SetToolRegistry(r *Registry, sessionID string) {
|
|||
}
|
||||
|
||||
// callPromotedTool executes a tool promoted via the registry by running the
|
||||
// script file directly as an executable.
|
||||
// script file directly inside the sandbox.
|
||||
func (e *Server) callPromotedTool(ctx context.Context, tool string, args json.RawMessage) (json.RawMessage, error) {
|
||||
// Resolve script path.
|
||||
if strings.Contains(tool, "/") || strings.Contains(tool, "..") {
|
||||
|
|
@ -281,7 +281,7 @@ func (e *Server) callPromotedTool(ctx context.Context, tool string, args json.Ra
|
|||
}
|
||||
path := filepath.Join(ToolsPath(), tool)
|
||||
|
||||
// Parse positional args.
|
||||
// Parse positional args into a shell command string.
|
||||
var positional []string
|
||||
var argMap map[string]interface{}
|
||||
if err := json.Unmarshal(args, &argMap); err == nil {
|
||||
|
|
@ -294,29 +294,25 @@ func (e *Server) callPromotedTool(ctx context.Context, tool string, args json.Ra
|
|||
}
|
||||
}
|
||||
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Execute the script directly — shebang handles the interpreter.
|
||||
e.wdMu.RLock()
|
||||
workDir := e.cwd
|
||||
e.wdMu.RUnlock()
|
||||
if workDir == "" {
|
||||
workDir, _ = os.Getwd()
|
||||
// Build a shell command that runs the tool script with its args.
|
||||
// Quote each arg for safe shell passing.
|
||||
quoted := make([]string, 0, len(positional)+1)
|
||||
quoted = append(quoted, path)
|
||||
for _, a := range positional {
|
||||
quoted = append(quoted, fmt.Sprintf("%q", a))
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, path, positional...)
|
||||
cmd.Dir = workDir
|
||||
code := strings.Join(quoted, " ")
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
// Execute through the sandbox via executeWithStdin.
|
||||
result, err := e.executeWithStdin(ctx, code, "bash", 30, "default", false, "")
|
||||
if err != nil {
|
||||
return json.Marshal(map[string]interface{}{
|
||||
"isError": true,
|
||||
"content": []map[string]string{{"type": "text", "text": string(output) + ": " + err.Error()}},
|
||||
"content": []map[string]string{{"type": "text", "text": result + ": " + err.Error()}},
|
||||
})
|
||||
}
|
||||
return json.Marshal(map[string]interface{}{
|
||||
"content": []map[string]string{{"type": "text", "text": string(output)}},
|
||||
"content": []map[string]string{{"type": "text", "text": result}},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Reference in New Issue