mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-09-03 22:17:04 +00:00
Address issues identified in PR #137 with a cleaner approach: - Sandbox isolation: add SandboxCwd/ResolveSandboxPath helpers to map filesystem tool paths to agent-scoped container subdirectories, preventing cross-agent file access via read/write/edit/list tools - DooD volume mounting: add resolveHostWorkspacePath with multi-strategy container ID detection (/proc/self/mountinfo, HOSTNAME, os.Hostname) and 5s timeout on docker inspect - Sandbox hints: expand from 1 pattern (binary not found) to 6 patterns (permission denied, network disabled, read-only FS, missing file, resource limits) with MaybeFsBridgeHint for filesystem tools - Nginx DNS: add Docker resolver (127.0.0.11) with dynamic upstream variable to handle backend container IP changes - MCP args: switch from comma-separated to space-separated parsing with quote support for --flag="value with spaces" patterns - Refactor: rename ExecTool.workingDir to workspace for consistency, extract sandbox.DefaultContainerWorkdir constant
46 lines
1.5 KiB
Go
46 lines
1.5 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// SandboxCwd maps the current effective workspace (from context) to its
|
|
// corresponding path inside the sandbox container. The sandbox mounts the
|
|
// global workspace root at containerBase (usually "/workspace"). This function
|
|
// computes the relative path from globalWorkspace to the context workspace
|
|
// and joins it with containerBase.
|
|
//
|
|
// Example: globalWorkspace="/app/workspace", ctx workspace="/app/workspace/agent-a/user-123"
|
|
// → returns "/workspace/agent-a/user-123"
|
|
func SandboxCwd(ctx context.Context, globalWorkspace, containerBase string) (string, error) {
|
|
ws := ToolWorkspaceFromCtx(ctx)
|
|
if ws == "" {
|
|
// No per-request workspace — fall back to container root.
|
|
return containerBase, nil
|
|
}
|
|
|
|
rel, err := filepath.Rel(globalWorkspace, ws)
|
|
if err != nil || strings.HasPrefix(filepath.Clean(rel), "..") {
|
|
return "", fmt.Errorf("workspace %q is outside global mount %q", ws, globalWorkspace)
|
|
}
|
|
|
|
if rel == "." {
|
|
return containerBase, nil
|
|
}
|
|
return filepath.Join(containerBase, rel), nil
|
|
}
|
|
|
|
// ResolveSandboxPath resolves a tool-provided path (relative or absolute)
|
|
// against the sandbox container CWD. If the path is relative, it is joined
|
|
// with containerCwd. Absolute paths are returned as-is (the sandbox
|
|
// filesystem already restricts access to the mounted volume).
|
|
func ResolveSandboxPath(path, containerCwd string) string {
|
|
if filepath.IsAbs(path) {
|
|
return path
|
|
}
|
|
return filepath.Join(containerCwd, path)
|
|
}
|