T05 · Unauthorized Access and Privilege Escalation
- Location
memory-transfer.js:20- Finding
Unvalidated Agent IDs Permit Workspace Path Traversal
- Content
View full analysis
Vulnerability Details
File Location:
memory-transfer.js, lines 20-35
Vulnerability Type: Filesystem path traversal and workspace-boundary bypass
Risk Level: HighVulnerable Code
js function getWorkspacePath(agentId) { // Check if it's a known agent const workspaceName = AGENT_WORKSPACES[agentId]; if (workspaceName) { return path.join(WORKSPACE_BASE, workspaceName); } // Try to find workspace const workspacePath = path.join(WORKSPACE_BASE, `workspace-${agentId}`); if (fs.existsSync(workspacePath)) { return workspacePath; } // Direct path return path.join(WORKSPACE_BASE, agentId); }The resulting target path is subsequently used for destructive filesystem operations:
js if (fs.existsSync(targetPath)) { const backupPath = targetPath + '.backup'; fs.renameSync(targetPath, backupPath); console.log(` ⚠️ Backed up existing: ${m.name} → ${m.name}.backup`); } // Copy file fs.copyFileSync(m.path, targetPath);Technical Analysis
The
sourceIdandtargetIdcommand-line arguments reachgetWorkspacePath()without validation. An unrecognized ID is incorporated into a path usingpath.join(). Inputs containing traversal components such as../can normalize to locations outside/home/node/.openclaw.The implementation checks only whether the resulting path exists. It does not use
path.resolve()orfs.realpathSync()to verify that the canonical path remains inside the permitted workspace base. It also does not reject symbolic links. Consequently, the same problem affects both source and target workspaces:- A crafted source ID can make the program inspect and copy qualifying files from an unintended directory.
- A crafted target ID can make the program rename and replace
MEMORY.mdor files under amemorydirectory outside an authorized agent workspace. - A symlinked workspace or memory directory can ...[truncated 1663 chars]
- Remediation
View remediation
Remediation Suggestions
-
Prefer an explicit allowlist and reject any agent ID not present in
AGENT_WORKSPACES. -
If dynamic IDs are required, enforce a restrictive identifier pattern such as
^[A-Za-z0-9_-]+$and reject dots, slashes, backslashes, absolute paths, and empty values. -
Resolve and canonicalize every workspace path before use:
js const base = fs.realpathSync(WORKSPACE_BASE); const candidate = path.resolve(base, `workspace-${agentId}`); const canonical = fs.realpathSync(candidate); if (canonical !== base && !canonical.startsWith(base + path.sep)) { throw new Error('Workspace path escapes the permitted base'); } -
Repeat containment validation for the final source file, target directory, and target file rather than checking only the workspace path.
-
Reject symbolic links for workspaces, memory directories, and destination files, or safely open files using platform facilities that prevent symlink following.
-
Avoid check-then-use races by using safe file descriptors and exclusive creation semantics where possible.
-
Run the utility under a dedicated, least-privileged account that can access only approved OpenClaw workspaces.
-
Add tests covering
../, absolute paths, nested traversal, alternate separators, symlink escapes, and traversal attempts in both source and target IDs.
-
