T09 · Insecure Skill Coding Practices
- Location
scripts/create_agent.py:88- Finding
Unvalidated workspace paths allow path traversal and arbitrary file overwrite
- Content
View full analysis
Vulnerability Details
File Location:
scripts/create_agent.py:88-95, 166-176, 196-203;scripts/clone_agent.py:175-183, 489-502, 619
Vulnerability Type: Path traversal and arbitrary file overwrite
Risk Level: HighVulnerable Code
scripts/create_agent.py:88-95python if workspace_dir: ws_base = Path(workspace_dir) else: ws_base = DEFAULT_WORKSPACE_BASE / agent_id / "workspace" ws_base.mkdir(parents=True, exist_ok=True) (ws_base / "memory").mkdir(exist_ok=True)scripts/create_agent.py:166-176python for filename, content in [ ("SOUL.md", soul_content), ("USER.md", user_content), ("AGENTS.md", agents_content), ("HEARTBEAT.md", "# 定期检查任务\n# (按需添加心跳任务)\n"), ]: (ws_base / filename).write_text(content, encoding="utf-8") return ws_basescripts/create_agent.py:196-203python parser = argparse.ArgumentParser(description="创建飞书群专属 Agent") parser.add_argument("--agent-id", required=True, help="Agent ID(英文,字母+数字+短横线)") parser.add_argument("--agent-name", required=True, help="Agent 中文显示名") parser.add_argument("--group-id", required=True, help="飞书群 ID(oc_xxx)") parser.add_argument("--duty", required=True, help="Agent 职责描述") parser.add_argument("--data-file", help="数据文件绝对路径(可选)") parser.add_argument("--daily-time", default="17:00", help="每日汇报时间(默认 17:00)") parser.add_argument("--weekly-time", default="周五 17:00", help="每周汇报时间") parser.add_argument("--workspace-dir", help="自定义 workspace 路径(可选)")scripts/clone_agent.py:175-183python def create_new_workspace(new_id: str, files: dict[str, str]) -> Path: new_ws = AGENTS_BASE / new_id / "workspace" new_ws.mkdir(parents=True, exist_ok=True) (new_ws / "memory").mkdir(exist_ok=True) for fname in ["SOUL.md", "USER.md", "AGENTS.md", "HEARTBEAT.md"]: if fname in files: (new_ws / fname).write_text(files[fname], encoding="utf-8 ...[truncated 3059 chars]- Remediation
View remediation
Remediation Suggestions
- Enforce the documented agent-ID syntax in both creation and cloning:
python import re AGENT_ID_PATTERN = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$") def validate_agent_id(value: str) -> str: if not AGENT_ID_PATTERN.fullmatch(value): raise ValueError("Invalid agent ID") return value - Resolve every generated workspace path and verify containment with
Path.is_relative_to():python base = DEFAULT_WORKSPACE_BASE.resolve() destination = (base / agent_id / "workspace").resolve() if not destination.is_relative_to(base): raise ValueError("Workspace path escapes the agent directory") - Remove
--workspace-dirunless arbitrary workspace roots are essential. If it must remain, restrict it to an explicit allowlist of trusted roots and require additional confirmation. - Reject absolute agent IDs, path separators,
.components, and..components before any filesystem operation. - Detect existing destination files and fail safely. If overwriting is required, display the exact affected paths and require a separate explicit confirmation.
- Add tests for absolute paths,
../traversal, nested traversal, symlink-based escapes, existing files, and valid agent IDs. - Validate the resolved destination again immediately before each write to reduce time-of-check/time-of-use and symlink risks.
- Enforce the documented agent-ID syntax in both creation and cloning:
