🤖 Generated by the Agentic Engineer
Evidence
The exec-bit guard (scripts/guard-tracked-exec-bit.sh, added in #3535) decides which scripts must be tracked 100755 by matching paths that textually contain scripts/ or .github/:
readonly SCRIPT_PATH_RE='(\.github|scripts)/[A-Za-z0-9_./-]+\.sh'
A workflow step can change the directory a command resolves against:
- name: something
working-directory: scripts
run: ./foo.sh
The runner directly execs the tracked scripts/foo.sh and therefore needs its execute bit, but ./foo.sh matches no modelled path, so no occurrence is produced. Because another invocation elsewhere satisfies the guard's anti-vacuity check, the run reports success rather than reporting that it could not tell — the same silent-pass failure mode the guard exists to remove, one level up.
Raised by Codex review on #3667 and confirmed valid there.
Affected audience and impact
CI correctness only; no production authorization surface is involved. Impact today is latent, not live — measured on the current tree:
working-directory: appears 3 times, all in publish-kubescape-storage-hotfix.yaml, all working-directory: upstream (a checked-out third-party repo) whose run: blocks invoke git, go and docker — no repository script.
- Relative
./*.sh invocations outside scripts/ and .github/: 0.
So nothing is being missed right now. The gap bites on the first step that combines a working directory with a relative script invocation, and it fails silent-green, which is the expensive direction.
Expected behaviour
A directly-invoked script that the guard cannot map to a tracked path must not pass silently. Either resolve the invocation against its step's working-directory (and equivalent cd in a run block), or fail closed naming the invocation it could not resolve, with the paved-road fix in the message.
Fail-closed is the smaller first increment and removes the silent-pass property on its own; resolution can follow. Note the ordering constraint found while fixing the sibling findings in #3667: any broadened extraction must still run through the prefix classifier, or bash ./foo.sh becomes a false positive — and false positives here fail every PR and merge-group run.
Acceptance criteria
- A fixture with
working-directory: plus a relative invocation of a script tracked 100644 does not exit 0.
- A fixture where that same script is handed to an interpreter still passes, so the fix is not "flag every relative path".
- The committed tree still reports the same directly-invoked script count (22 at time of writing), proving the change is conservative.
- Against the pre-change guard the new assertions fail and every existing assertion passes.
Rough size
Small-to-medium. Fail-closed detection is a contained change to extraction plus the classifier call path; full working-directory resolution is the larger half and can be a separate increment.
Evidence
The exec-bit guard (
scripts/guard-tracked-exec-bit.sh, added in #3535) decides which scripts must be tracked100755by matching paths that textually containscripts/or.github/:A workflow step can change the directory a command resolves against:
The runner directly execs the tracked
scripts/foo.shand therefore needs its execute bit, but./foo.shmatches no modelled path, so no occurrence is produced. Because another invocation elsewhere satisfies the guard's anti-vacuity check, the run reports success rather than reporting that it could not tell — the same silent-pass failure mode the guard exists to remove, one level up.Raised by Codex review on #3667 and confirmed valid there.
Affected audience and impact
CI correctness only; no production authorization surface is involved. Impact today is latent, not live — measured on the current tree:
working-directory:appears 3 times, all inpublish-kubescape-storage-hotfix.yaml, allworking-directory: upstream(a checked-out third-party repo) whoserun:blocks invokegit,goanddocker— no repository script../*.shinvocations outsidescripts/and.github/: 0.So nothing is being missed right now. The gap bites on the first step that combines a working directory with a relative script invocation, and it fails silent-green, which is the expensive direction.
Expected behaviour
A directly-invoked script that the guard cannot map to a tracked path must not pass silently. Either resolve the invocation against its step's
working-directory(and equivalentcdin a run block), or fail closed naming the invocation it could not resolve, with the paved-road fix in the message.Fail-closed is the smaller first increment and removes the silent-pass property on its own; resolution can follow. Note the ordering constraint found while fixing the sibling findings in #3667: any broadened extraction must still run through the prefix classifier, or
bash ./foo.shbecomes a false positive — and false positives here fail every PR and merge-group run.Acceptance criteria
working-directory:plus a relative invocation of a script tracked100644does not exit 0.Rough size
Small-to-medium. Fail-closed detection is a contained change to extraction plus the classifier call path; full
working-directoryresolution is the larger half and can be a separate increment.