diff --git a/.gitattributes b/.gitattributes index e18bdbe..bf0808a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -44,8 +44,9 @@ LICENSE text eol=lf *.dmg binary *.jmx binary *.har binary -*.png filter=lfs diff=lfs merge=lfs -text -*.jpg filter=lfs diff=lfs merge=lfs -text +# LFS disabled — git-lfs not installed on all dev machines +# *.png filter=lfs diff=lfs merge=lfs -text +# *.jpg filter=lfs diff=lfs merge=lfs -text # linguist(GitHub 语言识别) 05-代码示例/* linguist-language=Python diff --git a/.gitignore b/.gitignore index 55ec9d1..960a981 100644 --- a/.gitignore +++ b/.gitignore @@ -200,3 +200,6 @@ archive/ # ===== runtime 运行时产物(用户数据,不入仓)===== runtime/workspace/ runtime/web/tsconfig.tsbuildinfo + +# ===== 安全:可能含敏感数据的文件 ===== +*.har diff --git a/runtime/orchestrator/metrics/parser.py b/runtime/orchestrator/metrics/parser.py index 5a6dbad..ee76c4e 100644 --- a/runtime/orchestrator/metrics/parser.py +++ b/runtime/orchestrator/metrics/parser.py @@ -61,7 +61,7 @@ def parse_jmeter_jtl(csv_text: str) -> dict[str, Any]: try: elapsed_values.append(int(fields[elapsed_idx])) except ValueError: - continue + pass # corrupt elapsed, still check success below if fields[success_idx].strip().lower() != "true": failures += 1 diff --git a/runtime/orchestrator/workflows/test_coordinator.py b/runtime/orchestrator/workflows/test_coordinator.py index 0138366..8db930d 100644 --- a/runtime/orchestrator/workflows/test_coordinator.py +++ b/runtime/orchestrator/workflows/test_coordinator.py @@ -22,7 +22,7 @@ ) # Paths relative to project root -_PROJECT_ROOT = Path(__file__).resolve().parents[2] +_PROJECT_ROOT = Path(__file__).resolve().parents[3] _WORKSPACE = _PROJECT_ROOT / "workspace" @@ -74,6 +74,15 @@ def run(self, target: str) -> PipelineResult: console.print(f"Target: {target[:100]}{'...' if len(target) > 100 else ''}") console.print() + # Validate target path (prevent traversal) + if target and not target.startswith(("http://", "https://")): + resolved = Path(target).resolve() + if not str(resolved).startswith(str(_PROJECT_ROOT.resolve())): + result.ok = False + result.aborted_at = "preflight" + result.summary = f"Target outside workspace: {target}" + return result + # Phase 0: Pre-flight missing = self._preflight() if missing: