Skip to content

Code review · SEC-T1-06, private workdir for the test runners

review-code on claude/autopilot-promotion-t1-d6-hutw7a, range a2f87d3..c7ef6eb, 2026-10-28, tick 11. Reviewers: code-reviewer and security-reviewer, independent, in parallel. Format: README.md.

The change fixes SEC-T1-06 from the T1 code review: before T3 runs the harness on a sind submitter node (dev environment §4.1), run_scenarios.py must stop deleting and reusing the predictable shared directory /tmp/spectio-scenarios. Without --workdir, run_scenarios.py and run_corpus.py now create a fresh private directory with tempfile.mkdtemp (mode 0700) and print its path. An explicit --workdir is created with its missing parents under umask 077, resolved, and refused unless this user owns it, it is not a symlink, nobody else can write to it, and its resolved parents belong to this user or root (sticky if others can write, like /tmp); the resolved path is the one used. CI passes $RUNNER_TEMP/… and is unchanged.

Round Head code-reviewer security-reviewer
1 9954aa0 approve (0 blockers, 0 majors, 2 minors) approve (0 blockers, 0 majors, 3 minors)
2 f9a4d6e approve on the fix delta (0 blockers, 0 majors, 1 minor) not re-run (round 1 had minors only)
3 d31b2c9 approve on 3355a10..d31b2c9 (0 blockers, 0 majors, 2 minors) approve on 3355a10..d31b2c9 (0 blockers, 0 majors, 1 minor)
4 881a65d not re-run (round 3 had minors only) approve on d31b2c9..881a65d (0 blockers, 0 majors, 2 minors)
5 c7ef6eb not re-run (round 4 had minors only) approve on 881a65d..c7ef6eb (0 blockers, 0 majors, 0 minors)
CODE  step=SEC-T1-06  review=approve b/M/m=0/0/5  security=approve b/M/m=0/0/6  rounds=5  simplify=nochange -0/+0  tests=pass

code-simplifier ran twice and changed nothing: on f9a4d6e (each helper was one line) and on 3355a10..c7ef6eb (each line of make_workdir carries one approved check; the two copies stay identical). Round 5 tests, at c7ef6eb; the run and the refusal below were recorded at f9a4d6e and e8ab2f4, and c7ef6eb changes only docstrings and --help:

python3 -m unittest tests/pipelines/synthetic/test_golden.py tests/pipelines/real/test_run_corpus.py
Ran 26 tests in 0.043s

OK
$ python3 tests/pipelines/synthetic/run_scenarios.py --engine snakemake --only happy
workdir: /tmp/spectio-scenarios-jhnhhktp
PASS  snakemake happy                             17.2s
$ ls -ld /tmp/spectio-scenarios-jhnhhktp
drwx------ 3 root root 4096 Oct 28 08:11 /tmp/spectio-scenarios-jhnhhktp
$ mkdir /tmp/sh && chmod 777 /tmp/sh   # a parent others can write to, not sticky
$ python3 tests/pipelines/synthetic/run_scenarios.py --workdir /tmp/sh/wd --engine snakemake --only happy
--workdir /tmp/sh/wd: must be a directory you own that others cannot write to (chmod go-w), not a symlink, under directories that only you or root can change
$ echo $?
1
Id Severity Finding Status
CR-S06-1 minor run_corpus.py had the same predictable default (/tmp/spectio-corpus, rmtree under it) f9a4d6e (same mkdtemp default, unit test)
CR-S06-2 minor T1 Progress page, T1 review table and inbox #51 still called SEC-T1-06 open 0d93d25, squashed into integration as 7a2f1b0
SEC-S06-1 minor An explicit --workdir in shared /tmp (another user's directory, or a symlink) is still trusted d31b2c9 (owner, symlink and group/other write checks, created with mode 0700, unit tests)
SEC-S06-2 minor The T1 step test told contributors to use --workdir /tmp/t1 0d93d25, squashed into integration as 7a2f1b0 (the T1 How-to-test command drops --workdir; dated evidence transcripts stay as recorded)
SEC-S06-3 minor The private workdirs are never removed and can fill a login node's quota f9a4d6e (both docstrings say they are kept for debugging and how to remove them)
CR-S06-3 minor The cleanup command expanded to /spectio-* when TMPDIR is unset c9d53f9 (${TMPDIR:-/tmp})
SEC-S06-4 minor Only the last component of an explicit --workdir was checked; a parent another user owns or can write to allowed a swap after the check 881a65d (resolved parents must belong to this user or root, sticky if others can write; unit tests for a shared and a sticky parent)
CR-S06-4 minor Same parent gap as SEC-S06-4 (proposed a docstring note instead of a check) 881a65d (the check from SEC-S06-4; the docstring states the rule)
CR-S06-5 minor With umask 002 a directory the user made is refused without a hint 881a65d (the refusal names chmod go-w)
SEC-S06-4a minor The resolved parents were checked but the path as given was used, so a symlink on the way could be swapped after the check e8ab2f4 (the resolved path is checked and returned; unit test with a linked parent)
SEC-S06-4b minor Missing parents followed the umask, so with umask 002 the script refused a path it had just created e8ab2f4 (parents created under umask 077; unit test under umask 002)