T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- src/lib/mailbox.ts:64
- Finding
- Mailbox Path Traversal Through Unvalidated Agent Identifiers<![CDATA[ ## Vulnerability Details **File Location**: `src/lib/mailbox.ts:64-69`, `src/lib/mailbox.ts:109-112` **Vulnerability Type**: Path traversal and unauthorized filesystem write **Risk Level**: High ### Vulnerable Code ```typescript constructor(agentName: string, basePath?: string) { this.agent = agentName; this.basePath = basePath || path.join(process.env.HOME || '/tmp', '.openclaw', 'workspace', 'mailbox'); this.inboxPath = path.join(this.basePath, agentName, 'inbox'); this.sentPath = path.join(this.basePath, agentName, 'sent'); this.archivePath = path.join(this.basePath, agentName, 'archive'); this.logPath = path.join(this.basePath, agentName, 'mail.log'); this.initializePaths(); } ``` ```typescript // Save to recipient's inbox const recipientInboxPath = path.join(this.basePath, options.to, 'inbox'); fs.mkdirSync(recipientInboxPath, { recursive: true }); await this.saveMessage(message, recipientInboxPath); ``` ### Technical Analysis The constructor's `agentName` parameter and the `options.to` recipient value are incorporated directly into filesystem paths without validation or containment checks. Node.js path normalization processes `..` components, so a value such as `../../target` can cause the resulting path to escape the intended mailbox root. The `send()` method then recursively creates the resolved directory and writes a Markdown message into it. The constructor similarly creates inbox, sent, and archive directories based on an unvalidated agent name. No call to `path.resolve()` followed by a mailbox-root comparison is performed. The vulnerable operation remains limited by the operating-system privileges of the Node.js process, but it violates the application's intended mailbox boundary. ### Attack Path 1. An attacker gains access to the CLI or another caller of `Mailbox.send()`. 2. The attacker supplies a traversal-bearing recipient, for example: ```bash openclaw mail send \ --to "../../target" \ --subject ...[truncated 1071 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Enforce a strict identifier format for both sender and recipient names: ```typescript const AGENT_ID = /^[A-Za-z0-9_-]{1,64}$/; function validateAgentId(value: string): string { if (!AGENT_ID.test(value)) { throw new Error('Invalid agent identifier'); } return value; } ``` 2. Resolve every generated path and verify that it remains under the canonical mailbox root: ```typescript function resolveMailboxPath(basePath: string, agent: string, folder: string): string { const root = path.resolve(basePath); const candidate = path.resolve(root, agent, folder); if (!candidate.startsWith(root + path.sep)) { throw new Error('Mailbox path escapes configured root'); } return candidate; } ``` 3. Apply the same validation in the constructor and `send()`, rather than trusting API callers to validate input. 4. Reject absolute paths, `.` and `..` path components, path separators, NUL bytes, and control characters. 5. Run the mailbox process under a dedicated, least-privileged operating-system account. 6. Add tests covering Unix and Windows traversal forms, absolute paths, mixed separators, and encoded traversal inputs. ]]>
