T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- server.cjs:21
- Finding
- Arbitrary Local File Disclosure Through Path Traversal<![CDATA[ ## Vulnerability Details **File Location**: `server.cjs:21-31` **Vulnerability Type**: Path traversal and arbitrary file read **Risk Level**: High ### Vulnerable Code ```js // Serve static files if (req.method === 'GET') { let filePath = req.url === '/' ? '/index.html' : req.url; filePath = path.join(__dirname, filePath); const ext = path.extname(filePath); const types = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css' }; try { const content = fs.readFileSync(filePath); res.writeHead(200, { 'Content-Type': types[ext] || 'text/plain' }); res.end(content); } catch { res.writeHead(404); res.end('Not found'); } return; } ``` ### Technical Analysis The server passes the untrusted request URL directly to `path.join()` and subsequently to `fs.readFileSync()`. It does not decode and validate the path, restrict access to an explicit public directory, or verify that the normalized path remains beneath the project root. Traversal components can consequently cause the normalized path to escape `__dirname`. The server will return any resulting file that is readable by its operating-system account. Because the server uses Node.js's default listen behavior and does not authenticate requests, this flaw may be available to other hosts whenever port 8765 is network-reachable. ### Attack Path 1. The victim starts the application. 2. An attacker connects to port 8765. 3. The attacker submits a crafted GET request containing sufficient parent-directory components, such as a path targeting `../../../../etc/passwd`. 4. `path.join()` normalizes the traversal sequence into a path outside the project directory. 5. `fs.readFileSync()` reads the target using the server process's filesystem privileges. 6. The file contents are returned in the HTTP response. ### Impact Assessment An attacker can read files accessible to the server account. The exposed scope may include: - OpenClaw configuration and credentials. ...[truncated 275 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Serve only files from a dedicated public directory. - Decode the URL safely and reject malformed encoding, NUL bytes, backslashes, and traversal segments. - Resolve the requested path and verify containment before reading it: ```js const publicRoot = path.resolve(__dirname, 'public'); const requestPath = decodeURIComponent(new URL(req.url, 'http://localhost').pathname); const target = path.resolve(publicRoot, `.${requestPath}`); if (target !== publicRoot && !target.startsWith(publicRoot + path.sep)) { res.writeHead(403); res.end('Forbidden'); return; } ``` - Apply an explicit allowlist if only `index.html` is required. - Use a maintained static-file middleware rather than implementing path handling manually. - Run the process as a low-privilege account with no access to unrelated credentials. ]]>
