MCPcopy Index your code
hub / github.com/github/spec-kit / load

Method load

src/specify_cli/workflows/engine.py:505–547  ·  view source on GitHub ↗

Load a run state from disk. Validates ``run_id`` against ``_RUN_ID_PATTERN`` *before* building the lookup path. Without this guard, a caller passing a value like ``../escape`` (e.g. via ``specify workflow resume`` CLI argument) would interpolate path-traversal segmen

(cls, run_id: str, project_root: Path)

Source from the content-addressed store, hash-verified

503
504 @classmethod
505 def load(cls, run_id: str, project_root: Path) -> RunState:
506 """Load a run state from disk.
507
508 Validates ``run_id`` against ``_RUN_ID_PATTERN`` *before* building
509 the lookup path. Without this guard, a caller passing a value like
510 ``../escape`` (e.g. via ``specify workflow resume`` CLI argument)
511 would interpolate path-traversal segments into
512 ``runs_dir`` below, letting ``state_path.exists()`` probe arbitrary
513 paths and ``json.load`` read attacker-planted JSON from outside
514 the project's ``runs/`` directory. ``__init__`` already runs this
515 check on the stored ``state_data["run_id"]``, but that fires
516 *after* the file lookup — too late to prevent the disclosure.
517 Mirrors the precedent in ``agents._ensure_within_directory``.
518 """
519 cls._validate_run_id(run_id)
520 runs_dir = project_root / ".specify" / "workflows" / "runs" / run_id
521 state_path = runs_dir / "state.json"
522 if not state_path.exists():
523 msg = f"Run state not found: {state_path}"
524 raise FileNotFoundError(msg)
525
526 with open(state_path, encoding="utf-8") as f:
527 state_data = json.load(f)
528
529 state = cls(
530 run_id=state_data["run_id"],
531 workflow_id=state_data["workflow_id"],
532 project_root=project_root,
533 )
534 state.status = RunStatus(state_data["status"])
535 state.current_step_index = state_data.get("current_step_index", 0)
536 state.current_step_id = state_data.get("current_step_id")
537 state.step_results = state_data.get("step_results", {})
538 state.created_at = state_data.get("created_at", "")
539 state.updated_at = state_data.get("updated_at", "")
540
541 inputs_path = runs_dir / "inputs.json"
542 if inputs_path.exists():
543 with open(inputs_path, encoding="utf-8") as f:
544 inputs_data = json.load(f)
545 state.inputs = inputs_data.get("inputs", {})
546
547 return state
548
549 def append_log(self, entry: dict[str, Any]) -> None:
550 """Append a log entry to the run log.

Callers 15

load_speckit_manifestFunction · 0.45
get_speckit_versionFunction · 0.45
handle_vscode_settingsFunction · 0.45
merge_json_filesFunction · 0.45
_loadMethod · 0.45
_build_stackFunction · 0.45
_loadMethod · 0.45
_is_url_cache_validMethod · 0.45
_fetch_single_catalogMethod · 0.45
_loadMethod · 0.45
_is_url_cache_validMethod · 0.45

Calls 3

RunStatusClass · 0.85
_validate_run_idMethod · 0.80
getMethod · 0.45