T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/agent_sync.py:321- Finding
Query-Based Discovery Bypasses Project Isolation and Can Import Unrelated Private Transcripts
- Content
View full analysis
dict[str, list[Path]]: claude_base = Path(os.environ.get("CLAUDE_CONFIG_DIR", str(Path.home() / ".claude"))).expanduser() codex_base = Path(os.environ.get("CODEX_HOME", str(Path.home() / ".codex"))).expanduser() return { "claude": [claude_base / "projects"], "codex": [codex_base / "sessions", codex_base / "archived_sessions"], } def source_paths(agent: str, include_subagents: bool) -> list[tuple[str, Path]]: selected = ["claude", "codex"] if agent == "both" else [agent] result: list[tuple[str, Path]] = [] for source in selected: for root in session_roots()[source]: if not root.exists(): continue for path in root.rglob("*.jsonl"): if source == "claude" and not include_subagents and "subagents" in path.parts: continue result.append((source, path)) return result ``` ```python query_match = not args.query or session["relevance"] >= len(args.query) project_match = is_within(session.get("cwd"), project) if args.query: if not query_match: continue elif not project_match: continue session["project_match"] = project_match sessions.append(session) ``` The accepted sessions are subsequently rendered into an import packet: ```python def markdown_sessions(sessions: Sequence[dict[str, Any]]) -> str: if not sessions: return "_No matching visible sessions found._\n" lines: list[str] = [] for session in sessions: lines.extend( [ f"## {session['source'].title()} · {session['session_id']}", "", f"- Updated: {session['updated_at']}", f"- CWD: ...[truncated 3827 chars]- Remediation
View remediation
= len(args.query) project_match = is_within(session.get("cwd"), project) if not project_match: continue if not query_match: continue ``` 2. If cross-project search is a required feature, place it behind an explicit option such as `--include-outside-project`. The option should: - Default to disabled. - Emit a prominent privacy warning. - Require explicit confirmation for packet writes. - Clearly label every out-of-project result. - Be disallowed in unattended operation unless separately authorized. 3. Separate project-scoped discovery from global transcript search at the API level so a future refactor cannot accidentally omit the boundary check. 4. Treat transcript content as untrusted data: - Wrap imported messages in explicit inert-data delimiters. - Add a warning immediately before each transcript section that its content must not be executed or treated as instructions. - Escape or label instruction-like content rather than presenting it as ordinary operational guidance. 5. Avoid including full absolute source paths unless the operator explicitly requests them. Prefer redacted paths or stable local identifiers. 6. Add regression tests proving that: - Query mode rejects sessions whose CWD is outside the project. - Common query terms cannot cause cross-project imports. - An explicit override is required for global searches. - Out-of-project transcript text is never written without that override. ]]>
