From e6378c31cd9b6785d163bd03ea33cae614746036 Mon Sep 17 00:00:00 2001 From: starmen1265 Date: Mon, 9 Mar 2026 16:26:36 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E9=81=8D=E5=8E=86=E5=AE=89=E5=85=A8=E9=A3=8E=E9=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev-workflow/stats.py | 44 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/dev-workflow/stats.py b/dev-workflow/stats.py index d405533..fe25bc5 100644 --- a/dev-workflow/stats.py +++ b/dev-workflow/stats.py @@ -24,13 +24,47 @@ class StatsManager: Args: stats_file: 统计数据文件路径,默认为 ~/.dev-workflow/stats.json + 如果提供相对路径,将解析到 ~/.dev-workflow/ 目录内 + 如果提供绝对路径,必须在 ~/.dev-workflow/ 目录内 """ - if stats_file is None: - stats_dir = Path.home() / '.dev-workflow' - stats_dir.mkdir(parents=True, exist_ok=True) - stats_file = stats_dir / 'stats.json' + # 定义安全目录 + safe_dir = Path.home() / '.dev-workflow' + safe_dir.mkdir(parents=True, exist_ok=True) + + if stats_file is None: + self.stats_file = safe_dir / 'stats.json' + else: + stats_path = Path(stats_file) + + # 安全校验:防止路径遍历攻击 + if stats_path.is_absolute(): + # 绝对路径:必须解析到安全目录内 + try: + # 解析并验证路径在安全目录内 + resolved_path = stats_path.resolve() + safe_dir_resolved = safe_dir.resolve() + + # 检查路径是否以安全目录开头 + if not str(resolved_path).startswith(str(safe_dir_resolved)): + raise ValueError( + f"安全错误:stats_file 路径必须在 ~/.dev-workflow/ 目录内," + f"提供的路径:{stats_file}" + ) + + self.stats_file = resolved_path + except (OSError, RuntimeError) as e: + raise ValueError(f"无效的 stats_file 路径:{stats_file}") from e + else: + # 相对路径:检查是否包含路径遍历 + if '..' in stats_path.parts: + raise ValueError( + f"安全错误:stats_file 路径不能包含 '..'," + f"提供的路径:{stats_file}" + ) + + # 将相对路径解析到安全目录内 + self.stats_file = safe_dir / stats_path - self.stats_file = Path(stats_file) self._ensure_stats_file() def _filter_sensitive_data(self, data: Dict[str, Any]) -> Dict[str, Any]: