mirror of
https://github.com/usestrix/strix.git
synced 2026-08-16 09:26:39 +02:00
revalidate persisted workspace files when resuming a run
This commit is contained in:
@@ -390,15 +390,21 @@ def _load_resume_state(args: argparse.Namespace, parser: argparse.ArgumentParser
|
||||
args.workspace_mount = workspace_mount
|
||||
|
||||
# Replace the workspace files the run started with, unless this resume names
|
||||
# its own. A file deleted between runs is dropped rather than fatal: it is
|
||||
# context for the agent, not scope.
|
||||
# its own. The persisted record is revalidated like a fresh flag, so an
|
||||
# edited run.json cannot widen what a resume places. A file deleted between
|
||||
# runs is dropped rather than fatal: it is context for the agent, not scope.
|
||||
if not getattr(args, "workspace_files", None):
|
||||
args.workspace_files = [
|
||||
workspace_file
|
||||
restored = [
|
||||
f"{source_path}:{workspace_path}"
|
||||
for workspace_file in state.get("workspace_files") or []
|
||||
if isinstance(workspace_file, dict)
|
||||
and Path(str(workspace_file.get("source_path", ""))).is_file()
|
||||
and (source_path := Path(str(workspace_file.get("source_path") or ""))).is_file()
|
||||
and (workspace_path := str(workspace_file.get("workspace_path") or ""))
|
||||
]
|
||||
try:
|
||||
args.workspace_files = resolve_workspace_files(restored)
|
||||
except ValueError as error:
|
||||
parser.error(f"--resume {args.resume}: invalid workspace file: {error}")
|
||||
if workspace_mount:
|
||||
if not Path(workspace_mount).expanduser().is_dir():
|
||||
parser.error(
|
||||
|
||||
@@ -128,6 +128,68 @@ def test_resume_restores_a_target_less_workspace_mount(
|
||||
assert args.instruction == "audit the auth flow"
|
||||
|
||||
|
||||
def test_resume_revalidates_persisted_workspace_files(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
"""Resume places the same files again, and drops ones that went away."""
|
||||
work = tmp_path / "project"
|
||||
work.mkdir()
|
||||
kept = tmp_path / "wordlist.txt"
|
||||
kept.write_text("admin\n", encoding="utf-8")
|
||||
monkeypatch.chdir(tmp_path)
|
||||
_write_run_record(
|
||||
tmp_path / "strix_runs",
|
||||
"pentest_abcd",
|
||||
{
|
||||
"run_name": "pentest_abcd",
|
||||
"targets_info": [],
|
||||
"local_sources": [],
|
||||
"workspace_mount": str(work),
|
||||
"workspace_files": [
|
||||
{"source_path": str(kept), "workspace_path": "/workspace/lists/words.txt"},
|
||||
{"source_path": str(tmp_path / "gone.txt"), "workspace_path": "/workspace/g.txt"},
|
||||
],
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(sys, "argv", ["strix", "--resume", "pentest_abcd"])
|
||||
|
||||
args = cli_main.parse_arguments()
|
||||
|
||||
assert args.workspace_files == [
|
||||
{"source_path": str(kept), "workspace_path": "/workspace/lists/words.txt"}
|
||||
]
|
||||
|
||||
|
||||
def test_resume_rejects_an_edited_workspace_file_path(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
||||
) -> None:
|
||||
"""A hand-edited record cannot place a file outside the workspace."""
|
||||
work = tmp_path / "project"
|
||||
work.mkdir()
|
||||
source = tmp_path / "wordlist.txt"
|
||||
source.write_text("admin\n", encoding="utf-8")
|
||||
monkeypatch.chdir(tmp_path)
|
||||
_write_run_record(
|
||||
tmp_path / "strix_runs",
|
||||
"pentest_abcd",
|
||||
{
|
||||
"run_name": "pentest_abcd",
|
||||
"targets_info": [],
|
||||
"local_sources": [],
|
||||
"workspace_mount": str(work),
|
||||
"workspace_files": [
|
||||
{"source_path": str(source), "workspace_path": "/etc/cron.d/payload"}
|
||||
],
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(sys, "argv", ["strix", "--resume", "pentest_abcd"])
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
cli_main.parse_arguments()
|
||||
|
||||
assert "invalid workspace file" in capsys.readouterr().err
|
||||
|
||||
|
||||
def test_resume_reports_a_missing_workspace_directory(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user