From c5fd20db5a2bd7317d8a42df9c4cecd741f3106d Mon Sep 17 00:00:00 2001 From: Quratulain-bilal Date: Wed, 29 Jul 2026 12:38:55 +0500 Subject: [PATCH] fix: remove TOCTOU race in RunState.load Remove exists() check before open() and catch FileNotFoundError directly. This prevents a race where the file is deleted between check and open, while preserving the descriptive error message. --- src/specify_cli/workflows/engine.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/specify_cli/workflows/engine.py b/src/specify_cli/workflows/engine.py index 13fd633338..2a68bbe908 100644 --- a/src/specify_cli/workflows/engine.py +++ b/src/specify_cli/workflows/engine.py @@ -653,12 +653,13 @@ def load(cls, run_id: str, project_root: Path) -> RunState: cls._validate_run_id(run_id) runs_dir = project_root / ".specify" / "workflows" / "runs" / run_id state_path = runs_dir / "state.json" - if not state_path.exists(): + + try: + with open(state_path, encoding="utf-8") as f: + state_data = json.load(f) + except FileNotFoundError: msg = f"Run state not found: {state_path}" raise FileNotFoundError(msg) - - with open(state_path, encoding="utf-8") as f: - state_data = json.load(f) if not isinstance(state_data, dict): raise ValueError("Invalid run state: expected a JSON object") missing_fields = [