Tencent/WeKnora · error
sandbox: workspace write path %q is outside %s
Error message
sandbox: workspace write path %q is outside %s
What it means
WriteSessionWorkspaceFile sanitizes the requested path through cleanSessionWorkspaceWritePath before writing. This error is returned when the cleaned path is absolute and a real file path but does not live under the session workspace root /workspace (e.g. /etc/passwd, /tmp/x, /workspace-evil/file). The sandbox deliberately restricts writes to /workspace to keep agent output contained.
Source
Thrown at internal/sandbox/session_manager.go:1028
return "", fmt.Errorf(
"sandbox: session input path %q is outside %s",
filePath, SessionInputRoot,
)
}
// cleanSessionWorkspaceWritePath keeps model-authored writes inside the
// session workspace and out of the attachment tree. Validation is lexical
// (path.Clean plus prefix checks), matching cleanSessionWorkDir.
func cleanSessionWorkspaceWritePath(filePath string) (string, error) {
clean := path.Clean(strings.TrimSpace(filePath))
if !path.IsAbs(clean) || clean == "." || clean == "/" {
return "", fmt.Errorf("sandbox: workspace write path %q must be an absolute file path", filePath)
}
if clean == SessionWorkspaceRoot || clean == SessionOutputRoot || clean == SessionInputRoot {
return "", fmt.Errorf("sandbox: workspace write path %q is a directory, not a file", filePath)
}
if !strings.HasPrefix(clean, SessionWorkspaceRoot+"/") {
return "", fmt.Errorf("sandbox: workspace write path %q is outside %s", filePath, SessionWorkspaceRoot)
}
if strings.HasPrefix(clean, SessionInputRoot+"/") {
return "", fmt.Errorf("sandbox: session input %s is read-only", SessionInputRoot)
}
return clean, nil
}
// cleanSessionWorkDir keeps shell_exec inside directories we are willing to let
// an agent work in. Ordinary sessions get /workspace only.
//
// Validation is lexical (path.Clean plus prefix checks): a symlink under an
// allowed root that resolves elsewhere at execution time is not detected and
// that is intentional. The only caller that passes allowSkillsRoot also passes
// AsRoot and runs arbitrary install shell commands, so a symlink would grant
// nothing those commands cannot already reach via cd or absolute paths. For
// ordinary sessions the allowlist is unchanged and its lexical nature is
// pre-existing. The allowlist stops casual wandering and makes intent
// auditable; the real isolation boundary is the remote sandbox itself.View on GitHub (pinned to 988cbb0330)
Solutions
- Rewrite the path to be under /workspace, e.g. "/workspace/output/report.txt".
- Call filepath.Clean/Join yourself before calling and verify strings.HasPrefix(cleaned, "/workspace/") to fail fast with a clearer message.
- If the data is an input attachment, read it via the input-path API instead of attempting a write into /workspace/input.
Example fix
// before err := mgr.WriteSessionWorkspaceFile(ctx, session, "/tmp/report.txt", data) // after err := mgr.WriteSessionWorkspaceFile(ctx, session, "/workspace/output/report.txt", data)
Defensive patterns
Strategy: validation
Validate before calling
func isWorkspaceWritePath(p string) bool {
c := filepath.Clean(p)
return filepath.IsAbs(c) && strings.HasPrefix(c, "/workspace/") &&
c != "/workspace/input" && !strings.HasPrefix(c, "/workspace/input/")
}
if !isWorkspaceWritePath(p) { /* fix path before calling */ } Type guard
func safeWorkspacePath(p string) (string, bool) {
c := filepath.Clean(p)
if !filepath.IsAbs(c) || !strings.HasPrefix(c, "/workspace/") {
return "", false
}
return c, true
} Try / catch
out, err := mgr.WriteSessionWorkspaceFile(ctx, s, path, data)
if err != nil {
return fmt.Errorf("write workspace file %q: %w", path, err)
} Prevention
- Always build paths with filepath.Join("/workspace", rel) instead of string concatenation.
- Refuse user-supplied relative paths that contain ".." before joining.
- Keep a unit test asserting all write targets start with /workspace/.
When it happens
Trigger: Calling WriteSessionWorkspaceFile (or the test helper path) with a file path whose cleaned value is not prefixed by "/workspace/" — e.g. absolute paths to other directories, or paths that clean to something outside /workspace such as "/workspace/../etc/hosts".
Common situations: Hardcoding an OS temp path or a host-relative path instead of a /workspace-relative one; constructing paths with ".." segments that escape the workspace; migrating code that previously wrote to arbitrary directories.
Related errors
- path %q is outside this install's skill directory (%s); an i
- sandbox: remote docker host %q requires a TLS certificate di
- sandbox: docker network mode %q is not allowed; use "bridge"
- sandbox: session input %s is read-only
- sandbox: work dir %q is outside allowed roots (%s)
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/96389447b511ad6f.
Report an issue: GitHub.