T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/agent_manager.py:67
- Finding
- Path Traversal Enables Filesystem Access Outside the Agent Workspace<![CDATA[ ## Vulnerability Details **File Location**: `scripts/agent_manager.py`, lines 67–68, 135–183, and 193–210 **Vulnerability Type**: Path traversal and missing filesystem-boundary validation **Risk Level**: High ### Vulnerable Code ```python def get_agent_path(agent_id: str, base_path: str = DEFAULT_AGENTS_PATH) -> Path: return Path(base_path) / agent_id ``` The resulting unchecked path is used by agent-management operations: ```python def add_agent(agent_id: str, template: str = "default", base_path: str = DEFAULT_AGENTS_PATH, **kwargs) -> dict: agent_path = get_agent_path(agent_id, base_path) if agent_path.exists(): return {"error": f"Agent {agent_id} already exists"} tmpl = AGENT_TEMPLATES.get( template, AGENT_TEMPLATES["default"] ).copy() tmpl.update(kwargs) agent_path.mkdir(parents=True, exist_ok=True) (agent_path / "memory").mkdir(exist_ok=True) soul_content = tmpl.get( "soul", AGENT_TEMPLATES["default"]["soul"] ) soul_content = soul_content.format( name=tmpl.get("name", agent_id) ) (agent_path / "SOUL.md").write_text(soul_content) (agent_path / "AGENTS.md").write_text(agents_content) (agent_path / "memory" / "experience.md").write_text( experience_content ) ``` ```python def remove_agent(agent_id: str, base_path: str = DEFAULT_AGENTS_PATH, backup: bool = True) -> dict: agent_path = get_agent_path(agent_id, base_path) if not agent_path.exists(): return {"error": f"Agent {agent_id} does not exist"} if backup: import shutil backup_path = Path(base_path) / ( f".backup_{agent_id}_" f"{datetime.now().strftime('%Y%m%d_%H%M%S')}" ) shutil.move(str(agent_path), str(backup_path)) else: import shutil shutil.rmtree(agent_path) ``` ### Technical Analysis `agent_id` is accepted from the command line and concatenated with t ...[truncated 2319 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict agent identifiers to a conservative allowlist, such as: ```python import re AGENT_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{1,64}$") def validate_agent_id(agent_id: str) -> str: if not AGENT_ID_PATTERN.fullmatch(agent_id): raise ValueError("Invalid agent identifier") return agent_id ``` 2. Resolve the base and target paths and enforce strict containment: ```python def get_agent_path(agent_id: str, base_path: str = DEFAULT_AGENTS_PATH) -> Path: validate_agent_id(agent_id) base = Path(base_path).resolve(strict=True) target = (base / agent_id).resolve(strict=False) if target.parent != base: raise ValueError("Agent path escapes the configured workspace") return target ``` 3. Reject absolute paths, path separators, `.` and `..` components, null bytes, and symlink-based escapes. 4. For destructive operations, resolve and revalidate the path immediately before deletion. Explicitly reject deletion of the base directory or any ancestor. 5. Require interactive confirmation or a separate authorization flag for permanent deletion. Prefer moving agents into a dedicated backup directory whose path is not derived from `agent_id`. 6. Run the management script with a dedicated, minimally privileged operating-system account restricted to the agent workspace. 7. Add tests covering absolute paths, traversal sequences, nested separators, symlinks, base-directory deletion, and malformed Unicode path components. ]]>
