T09 · Insecure Skill Coding Practices
- Location
scripts/graph_manager.py:41- Finding
Path Traversal in Local Graph Storage
- Content
View full analysis
Vulnerability Details
File Location:
scripts/graph_manager.py:41-43, 47-60, 70-81, 270-284
Vulnerability Type: Path traversal leading to unauthorized file access, modification, or deletion
Risk Level: HighVulnerable Code
python def _get_graph_path(self, pipeline_id: str) -> str: """获取图谱文件路径""" return os.path.join(self.storage_dir, f"{pipeline_id}.json")The resulting path is used directly by file operations:
python def _load_graph(self, pipeline_id: str) -> Dict: """加载图谱数据""" # 先检查缓存 if pipeline_id in self.cache: return self.cache[pipeline_id] # 从文件加载 graph_path = self._get_graph_path(pipeline_id) if os.path.exists(graph_path): try: with open(graph_path, 'r', encoding='utf-8') as f: data = json.load(f) self.cache[pipeline_id] = data return data except (json.JSONDecodeError, Exception): passpython def _save_graph(self, pipeline_id: str, data: Dict): """保存图谱数据""" graph_path = self._get_graph_path(pipeline_id) # 更新缓存 self.cache[pipeline_id] = data # 保存到文件 with open(graph_path, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2)python def delete_graph(self, pipeline_id: str) -> Dict: """ 删除图谱 Args: pipeline_id: 管道ID Returns: 删除结果 """ # 清除缓存 if pipeline_id in self.cache: del self.cache[pipeline_id] # 删除文件 graph_path = self._get_graph_path(pipeline_id) if os.path.exists(graph_path): os.remove(graph_path) return {"success": True, "message": "图谱已删除"} return {"success": False, "error": "图谱不存在"}Technical Analysis
pipeline_idis concatenated into a filesystem path without vali ...[truncated 1561 chars]- Remediation
View remediation
Remediation Suggestions
- Restrict
pipeline_idto an explicit allowlist pattern, such as^[A-Za-z0-9_-]+$. - Reject absolute paths, path separators,
.segments, and..segments. - Resolve both the storage directory and destination path to canonical paths before every operation.
- Verify that the resolved destination is a child of the resolved storage directory using
Path.is_relative_to()or an equivalent safe containment test. - Use an internal server-generated identifier rather than accepting arbitrary identifiers at the storage boundary.
- Open files using safer flags where appropriate, and consider preventing symbolic-link traversal.
- Apply the same validation to read, write, cache, and delete operations.
Example hardening:
python import re from pathlib import Path def _get_graph_path(self, pipeline_id: str) -> str: if not re.fullmatch(r"[A-Za-z0-9_-]+", pipeline_id): raise ValueError("Invalid pipeline identifier") base = Path(self.storage_dir).resolve() target = (base / f"{pipeline_id}.json").resolve() if not target.is_relative_to(base): raise ValueError("Graph path escapes the storage directory") return str(target)- Restrict
