T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- index.js:273
- Finding
- Arbitrary Local File Disclosure Through Unrestricted Absolute Paths<![CDATA[ ## Vulnerability Details **File Location**: `index.js:273-281`, `index.js:352-356` **Vulnerability Type**: Missing file-access authorization and path restriction **Risk Level**: High ### Vulnerable Code ```javascript // Match absolute paths const absPathMatch = text.match(/(\/[^\s]+)/g) if (absPathMatch) { for (const p of absPathMatch) { if (p.startsWith('/') && !p.startsWith('/open-apis') && !p.startsWith('/api') && fs.existsSync(p)) { return p } } } ``` ```javascript // Attempt to extract a file path directly let filePath = extractFilePath(userInput) if (filePath && fs.existsSync(filePath)) { await sendFile(context, token, filePath, isGroup, chatId, openId) return } ``` ### Technical Analysis The Skill treats any existing absolute path contained in a chat message as an authorized file to transmit. Validation is limited to checking that the path exists and does not begin with `/open-apis` or `/api`. The implementation does not: - Restrict files to the OpenClaw workspace or another approved directory. - Verify that the caller is authorized to access the requested file. - Require confirmation before transmitting sensitive files. - Resolve and validate canonical paths. - Prevent symbolic-link escapes. - Verify that the target is a regular file. - Restrict sensitive file names, directories, or file types. The file is subsequently read using the OpenClaw process's operating-system privileges, uploaded to Feishu, and sent to the current group or private conversation. This creates a confused-deputy condition: a chat participant may use the bot's filesystem permissions to retrieve files that the participant could not access directly. ### Attack Path 1. An attacker gains access to a conversation in which the Skill can be invoked. 2. The attacker submits a request containing a sensitive absolute path, for example: ```text Send file /home/node/.openclaw/openclaw.json ``` 3. `extractFilePath()` finds the path and accept ...[truncated 1265 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict file transmission to explicitly approved root directories, such as a dedicated outbound-files directory. 2. Resolve both the approved root and requested path with `fs.realpathSync()` before validation. 3. Verify that the canonical requested path remains inside the canonical approved root: ```javascript const root = fs.realpathSync(approvedRoot) const requested = fs.realpathSync(inputPath) const relative = path.relative(root, requested) if (relative.startsWith('..') || path.isAbsolute(relative)) { throw new Error('The requested file is outside the approved directory') } ``` 4. Use `fs.lstatSync()` and `fs.statSync()` to reject symbolic links, directories, devices, FIFOs, sockets, and other non-regular files. 5. Apply caller-level authorization. Only explicitly permitted Feishu users or groups should be able to invoke file transmission. 6. Require explicit confirmation that shows the canonical path, recipient, and file size before uploading sensitive or externally supplied paths. 7. Consider maintaining a server-generated file identifier list instead of accepting arbitrary paths from chat text. 8. Deny known-sensitive directories and file patterns as defense in depth, including OpenClaw configuration, credentials, SSH material, and environment files. 9. Add security tests for path traversal, symbolic-link escape, sensitive absolute paths, unauthorized callers, and non-regular files. ]]>
