T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/search_sessions.py:25
- Finding
- Unrestricted Cross-Agent Access to Private Session Transcripts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/search_sessions.py:25-34, 37-68, 122-143, 169-204`; `SKILL.md:8, 25-29` **Vulnerability Type**: Cross-agent transcript access without an enforced authorization boundary **Risk Level**: Medium ### Vulnerable Code `scripts/search_sessions.py:25-34` enumerates the session directories of every locally configured agent: ```python def find_session_dirs(): """Find all agent session directories.""" base = Path.home() / ".openclaw" / "agents" dirs = {} if base.exists(): for agent_dir in base.iterdir(): sessions_dir = agent_dir / "sessions" if sessions_dir.is_dir(): dirs[agent_dir.name] = sessions_dir return dirs ``` `scripts/search_sessions.py:37-68` reads complete JSONL transcript files and extracts message contents: ```python def parse_session(path: Path): """Parse a JSONL session file into metadata + messages.""" meta = {} messages = [] try: with open(path) as f: for line in f: line = line.strip() if not line: continue obj = json.loads(line) t = obj.get("type") if t == "session": meta = obj elif t == "message": msg = obj.get("message", {}) role = msg.get("role", "") content = msg.get("content", "") # Extract text from content array if isinstance(content, list): texts = [] for block in content: if isinstance(block, dict) and block.get("type") == "text": texts.append(block.get("text", "")) text = "\n".join(texts) elif isinstance(content, str): text = content else: ...[truncated 5925 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Default to the current agent only** - Resolve the current agent identity from trusted runtime context. - Search only that agent's session directory unless an authorized administrator explicitly enables broader access. - Do not use all discovered agent directories as the default. 2. **Enforce authorization before file access** - Maintain an allowlist of agent IDs the caller may access. - Validate authorization before invoking `parse_session`. - Do not rely solely on possession of local filesystem permissions as application-level authorization. 3. **Require explicit consent for cross-agent searches** - Present the exact agents and scope to be searched. - Require confirmation before reading another agent's transcripts. - Record an audit event for approved cross-agent access. 4. **Minimize disclosed information** - Return session metadata by default rather than message excerpts. - Make excerpts opt-in and redact likely secrets, credentials, personal information, and access tokens. - Avoid exposing absolute transcript paths unless required for an authorized administrative operation. 5. **Restrict direct transcript retrieval** - Remove the documented direct-file-read fallback for ordinary users. - Permit full transcript retrieval only for an explicitly selected and authorized session. - Validate that canonicalized paths remain within the authorized agent's session directory. 6. **Apply resource and retention controls** - Limit file sizes and the number of transcripts parsed per invocation. - Define transcript retention and deletion policies. - Restrict transcript filesystem permissions to the minimum necessary principals. 7. **Add security tests** - Verify that a caller scoped to one agent cannot search or read another agent's sessions. - Verify that omitting `--agent` never broadens access. - Test canonical path containment and denial of unauthorized agent iden ...[truncated 91 chars]
