T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- server.js:20
- Finding
- Unauthenticated filesystem disclosure and arbitrary file overwrite<![CDATA[ ## Vulnerability Details **File Location**: `server.js:20-81` **Vulnerability Type**: Missing authorization and improper path validation **Risk Level**: Critical ### Vulnerable Code ```javascript // REALPATH endpoint (GET /realpath?path=...) if (req.method === 'GET' && parsedUrl.pathname === '/realpath') { try { const filePath = parsedUrl.query.path; const fullPath = path.join(ENGINE_DIR, filePath); const realPath = fs.realpathSync(fullPath); const basename = path.basename(realPath); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ basename })); } catch (error) { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: error.message })); } return; } // WRITE endpoint (POST /write) if (req.method === 'POST' && parsedUrl.pathname === '/write') { let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { try { const { path: filePath, content } = JSON.parse(body); const fullPath = path.join(ENGINE_DIR, filePath); // Security: only allow writes within engine directory if (!fullPath.startsWith(ENGINE_DIR)) { res.writeHead(403, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'Path outside engine directory' })); return; } fs.writeFileSync(fullPath, content, 'utf8'); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ success: true })); } catch (error) { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: error.message })); } }); return; } // READ endpoint (GET files) let filePath = parsedUrl.pathname === '/' ? '/index.html' : parsedUrl.pathname; filePath = path.join(ENGINE_DIR, filePath); const ext = path.extname(filePath); const contentType = mimeTypes[ext] || 'application/octet-stream'; fs.read ...[truncated 2628 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Bind the service explicitly to `127.0.0.1` or a Unix-domain socket. 2. Generate a cryptographically random authorization token for every launch and require it on all privileged endpoints. 3. Reject requests with untrusted `Origin` or `Host` headers and implement CSRF protection. 4. Remove the generic file-read and file-write APIs. Use an explicit allowlist containing only the selected Markdown document. 5. Canonicalize both the allowed root and requested target before access. Use `path.resolve`, `fs.realpath`, and `path.relative` rather than string-prefix comparisons. 6. Reject a target when the relative path is absolute, equals `..`, or begins with `..${path.sep}`. 7. Reject symbolic links or open files using platform protections that prevent symlink following where available. 8. Prevent the document-editing endpoint from writing engine code, HTML, JavaScript, shell scripts, or files outside a dedicated content directory. 9. Perform intended updates atomically using a temporary file, validation, backup, and rename. 10. Run the service under a dedicated low-privilege account with filesystem access limited to the selected document. ]]>
