The vulnerability is a path traversal issue caused by improper handling of symbolic links in temporary directory creation and file path validation. The root cause lies in the resolvePreferredOpenClawTmpDir function in src/infra/tmp-openclaw-dir.ts. When its primary temporary directory is unavailable, it falls back to a user-specific directory in the OS's temporary folder without ensuring this fallback path is not a symlink. An attacker can pre-create this fallback path as a symlink to /.
Subsequently, other parts of the application that handle file operations, such as downloads and trace saving, trust this temporary directory to be a safe root. Functions like resolvePathWithinRoot in src/browser/paths.ts were used to validate that file paths are within this root. However, resolvePathWithinRoot only performed lexical checks and did not resolve symlinks.
This combination allows an attacker to bypass the sandbox. For example, a request to download a file to $TMPDIR/openclaw-<uid>/etc/passwd would pass the resolvePathWithinRoot check because lexically it is inside the temporary directory. But because $TMPDIR/openclaw-<uid> is a symlink to /, the application would actually write to or read from /etc/passwd.
The patch addresses this in two ways:
- It hardens
resolvePreferredOpenClawTmpDir by adding ensureTrustedFallbackDir, which validates that the fallback directory is a real, trusted directory and not a symlink.
- It replaces the insecure
resolvePathWithinRoot with a new resolveWritablePathWithinRoot function. This new function explicitly checks for symlinks in the path and ensures the real, canonicalized path of the target file is within the intended root directory. This change is applied in src/browser/routes/agent.act.ts and src/browser/routes/agent.debug.ts, which handle file downloads and trace outputs.