T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- generate.js:37
- Finding
- Cross-User Disclosure Through Global Feishu Session Selection<![CDATA[ ## Vulnerability Details **File Location**: `generate.js:37-88` **Vulnerability Type**: Missing user-to-session authorization binding **Risk Level**: High ### Vulnerable Code ```js const SESSIONS_DIR = '/root/.openclaw/agents/main/sessions'; const SESSIONS_FILE = path.join(SESSIONS_DIR, 'sessions.json'); // Read sessions.json and locate the latest Feishu session const sessionsData = JSON.parse(fs.readFileSync(SESSIONS_FILE, 'utf-8')); // Find the latest Feishu session file let latestFeishuSession = null; let latestTime = 0; for (const [key, session] of Object.entries(sessionsData)) { if (key.includes('feishu:direct') && session.updatedAt) { if (session.updatedAt > latestTime) { latestTime = session.updatedAt; latestFeishuSession = session; } } } if (!latestFeishuSession || !latestFeishuSession.sessionFile) { console.log('⚠️ No Feishu session found; skipping session history'); return ''; } const sessionFile = latestFeishuSession.sessionFile; if (!fs.existsSync(sessionFile)) { console.log('⚠️ Session file does not exist:', sessionFile); return ''; } // Read the JSONL file const lines = fs.readFileSync(sessionFile, 'utf-8').split('\n'); const messages = []; const today = new Date(); const todayStr = today.toISOString().split('T')[0]; lines.forEach(line => { if (!line.trim()) return; try { const entry = JSON.parse(line); if (entry.type === 'message' && entry.message) { const timestamp = new Date(entry.timestamp).toISOString().split('T')[0]; if (timestamp >= todayStr) { messages.push({ role: entry.message.role, content: entry.message.content?.[0]?.text || '' }); } } } catch (e) { // Skip lines that cannot be parsed } }); ``` ### Technical Analysis The report generator does not bind session selection to an explicitly authorized Feishu user, conversation identifier, or report recipient. Instead, it iterates over every entry whose key contai ...[truncated 1706 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Add an explicit authorized Feishu user ID, conversation ID, or session key to the configuration. 2. Resolve only the session associated with that configured identity; do not select a direct-message session globally by timestamp. 3. Verify that the source-session owner matches the intended report recipient before reading the session file. 4. Reject ambiguous, missing, or mismatched identity information and fail closed rather than falling back to another recent session. 5. Validate that `sessionFile` resolves beneath the expected sessions directory before reading it. 6. Apply least-privilege filesystem permissions so the report process can access only the intended session and memory files. 7. Record source and destination identity metadata in audit logs without logging message content. 8. Add automated tests involving multiple simultaneous Feishu users to ensure that content cannot cross conversation boundaries. ]]>
