Lane: merge-drive (deferred finding from PR #947, branch fix/549-credential-roots-allowlist).
Source. Codex P2 thread "Require credential probes below directory roots" on plugins/autonomy/skills/setup/scripts/check-security-binding.mjs — pathUnderConfiguredRoot equality case plus the credentials_absent grading (~L1340-1370).
Finding. When an operator configures a directory as a --credential-roots entry (e.g. /home/runner/.aws), a transcript whose probed path/host_expanded equals that directory passes containment via the equality case (normCandidate === normRoot). A directory reliably satisfies every downstream check: the outer existence probe succeeds (outer_exit_code "0"), the inner file-read fails with a directory-read error (non-zero exit_code, transport_outcome "read-denied"). The checker therefore grants L2 credential-absence even though real credential files beneath the directory (e.g. /home/runner/.aws/credentials) remain readable and were never probed.
Classification. Over-permissive edge in the deny-by-default credential allowlist (accepts non-probative evidence, feeding an autonomy-binding grant). Not the vacuous-root class already fixed on-branch for POSIX / and bare drive roots: a directory root still genuinely constrains the allowlist and requires the operator to have configured that exact directory, so this is a narrower hardening refinement, not a fail-open that makes the allowlist vacuous. Deferred rather than point-fixed, consistent with #549's ratified anti-enumeration posture (operator-configured roots are the convergence mechanism; do not re-enter open-ended structural recognition).
Why not point-fixed on-branch. The static transcript checker cannot stat the probing host, and the transcript records no errno/file-type — transport_outcome is coarse ("read-denied") and cannot distinguish an EISDIR directory-read from a credential-file read failure. So no clean generic fix exists: (a) structural file-vs-directory heuristics on the path string are exactly the open-ended structural recognition #549 closed; (b) dropping the equality case would deny the legitimate config where an operator configures an exact credential file as a root and the probe targets that file, with regression-test blast radius.
Fix direction (for #549 follow-up design). Decide whether directory roots should require strict-descendant containment (equality reserved for exact credential-file roots), and add a file-type/errno signal to the probe transcript contract (templates/isolation-probe.md) so a directory-read (EISDIR) is rejected as non-probative. Both are contract/design changes, not point-fixes.
Related. #549 (ratified Option A — deny-by-default --credential-roots), PR #947.
Lane: merge-drive (deferred finding from PR #947, branch
fix/549-credential-roots-allowlist).Source. Codex P2 thread "Require credential probes below directory roots" on
plugins/autonomy/skills/setup/scripts/check-security-binding.mjs—pathUnderConfiguredRootequality case plus thecredentials_absentgrading (~L1340-1370).Finding. When an operator configures a directory as a
--credential-rootsentry (e.g./home/runner/.aws), a transcript whose probedpath/host_expandedequals that directory passes containment via the equality case (normCandidate === normRoot). A directory reliably satisfies every downstream check: the outer existence probe succeeds (outer_exit_code"0"), the inner file-read fails with a directory-read error (non-zeroexit_code,transport_outcome"read-denied"). The checker therefore grants L2 credential-absence even though real credential files beneath the directory (e.g./home/runner/.aws/credentials) remain readable and were never probed.Classification. Over-permissive edge in the deny-by-default credential allowlist (accepts non-probative evidence, feeding an autonomy-binding grant). Not the vacuous-root class already fixed on-branch for POSIX
/and bare drive roots: a directory root still genuinely constrains the allowlist and requires the operator to have configured that exact directory, so this is a narrower hardening refinement, not a fail-open that makes the allowlist vacuous. Deferred rather than point-fixed, consistent with #549's ratified anti-enumeration posture (operator-configured roots are the convergence mechanism; do not re-enter open-ended structural recognition).Why not point-fixed on-branch. The static transcript checker cannot stat the probing host, and the transcript records no errno/file-type —
transport_outcomeis coarse ("read-denied") and cannot distinguish anEISDIRdirectory-read from a credential-file read failure. So no clean generic fix exists: (a) structural file-vs-directory heuristics on the path string are exactly the open-ended structural recognition #549 closed; (b) dropping the equality case would deny the legitimate config where an operator configures an exact credential file as a root and the probe targets that file, with regression-test blast radius.Fix direction (for #549 follow-up design). Decide whether directory roots should require strict-descendant containment (equality reserved for exact credential-file roots), and add a file-type/errno signal to the probe transcript contract (
templates/isolation-probe.md) so a directory-read (EISDIR) is rejected as non-probative. Both are contract/design changes, not point-fixes.Related. #549 (ratified Option A — deny-by-default
--credential-roots), PR #947.