T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/ct_integrate.py:13- Finding
Arbitrary Local File Read Through Attacker-Controlled Topology Paths
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ct_integrate.py:13-45;scripts/ct_archive.py:130-148
Vulnerability Type: Path traversal and unrestricted local file read
Risk Level: HighVulnerable Code
scripts/ct_integrate.py:13-45:python def main(): topo_file = sys.argv[1] if len(sys.argv) > 1 else "/root/.openclaw/workspace/cognitive-topology/topology_latest.json" if not os.path.exists(topo_file): print(f"❌ 拓扑文件不存在: {topo_file}") sys.exit(1) with open(topo_file, 'r', encoding='utf-8') as f: topo = json.load(f) print(f"📊 整合拓扑: {topo['id']}") print(f"📝 主任务: {topo['task']}") print() all_l2 = [] done_count = 0 for branch in topo.get("branches", []): l2_file = branch.get("l2_file") status = branch.get("status", "unknown") # 优先读JSON中的status,其次读文件内容 if status != "done" and l2_file and os.path.exists(l2_file): with open(l2_file, 'r', encoding='utf-8') as f: content = f.read() if "*(待填写)*" not in content: status = "done" icon = '✅' if status == 'done' else '⏳' print(f"{icon} {branch['id']} [{status}]") if status == 'done' and l2_file and os.path.exists(l2_file): with open(l2_file, 'r', encoding='utf-8') as f: content = f.read() all_l2.append({"branch_id": branch["id"], "content": content})scripts/ct_archive.py:130-148:python if not os.path.exists(topo_file): print(f"❌ 拓扑文件不存在: {topo_file}") sys.exit(1) with open(topo_file, 'r', encoding='utf-8') as f: topo = json.load(f) print(f"📦 归档拓扑: {topo['id']}") print(f"📝 任务: {topo['task']}") print() branch_summaries = [] all_tags = set() for ...[truncated 3222 chars]- Remediation
View remediation
Remediation Suggestions
- Canonicalize every branch path with
pathlib.Path.resolve(strict=True). - Require the resolved path to be a regular file located beneath the canonical
BRANCH_DIR. - Reject absolute paths supplied by topology documents; preferably store only branch identifiers or basenames and construct the full path internally.
- Reject symbolic links or open files using platform protections such as
O_NOFOLLOWwhere available. - Enforce an allowlisted filename pattern, such as
ct-[0-9]+-[0-9]{2}_L2.md. - Validate topology documents against a strict schema before processing them.
- Apply size limits before reading files to prevent resource exhaustion.
- Run the scripts under a dedicated, least-privileged account that cannot read credentials or unrelated system files.
- Avoid automatically placing raw branch contents into agent-consumed synthesis or memory files.
Example containment check:
python from pathlib import Path branch_root = Path(BRANCH_DIR).resolve() candidate = Path(l2_file).resolve(strict=True) if candidate.parent != branch_root: raise ValueError("Branch file is outside the permitted directory") if candidate.is_symlink() or not candidate.is_file(): raise ValueError("Invalid branch file")- Canonicalize every branch path with
