Execution mode: implementation
Depends on: none
Bug Summary
scripts/test-install-managed-migrations.sh uses rg for its final secret-leak assertion, but does not distinguish “no match” from “command unavailable”. In the current GitHub Actions environment, the script emitted rg: command not found and then still printed its PASS line.
This creates a false-green CI security assertion: exit status 127 from a missing rg binary is treated by the shell if exactly like a normal non-match.
Current Behaviour
The final assertion is equivalent to:
if rg -F "$TEST_SECRET" "$TEST_ROOT" --glob '!forge.env' >/dev/null; then
fail "managed local installer persisted a generated secret outside forge.env"
fi
printf 'PASS: managed local migration orchestration coverage\n'
Observed in Web CI while reviewing PR #361:
scripts/test-install-managed-migrations.sh: line 1341: rg: command not found
PASS: managed local migration orchestration coverage
Expected Behaviour
The proof must fail closed if its search dependency is unavailable, or use a guaranteed/fallback search mechanism. “Tool missing” must never be interpreted as “secret absent”.
Recommended Remediation
Preflight the declared scanner dependency and handle its actual exit status explicitly: match means leak/assertion failure; documented no-match with no error may continue; missing command, unreadable input, invalid invocation, signal or any other error fails the proof. Preflight alone is insufficient. Apply the same total-status handling to the script's negative-content assertion helper.
Keep fixed-string/option-safe arguments, bounded fixture scope and explicit allowed environment-file exclusions. Test missing/error paths executablely, not just by checking source text. Full architecture and regression matrix: #362 (comment)
Scope
This is independent of #354 / PR #361’s readiness-control-plane code and should be fixed separately so it does not reset that PR’s final-source review gate.
Reproduction Steps
- On the reviewed main baseline, inspect the final search in scripts/test-install-managed-migrations.sh.
- Run the existing fixture with all other required dependencies present but ripgrep unavailable from PATH.
- Observe that the conditional treats the missing-command status as a non-match and can reach PASS; the original Web CI observation above records this behaviour.
- Repeat with a scanner stub that returns an error status and with a missing input to assert_not_contains. These are required executable regression cases, not newly run evidence in this planning update.
Impact
The managed-migration security proof can report success without completing its secret-leak/negative-content assertions. This weakens CI evidence; it does not establish that a real production secret leaked.
Severity
P1 / high proof-integrity defect.
Acceptance Criteria
Primary Code Seams
scripts/test-install-managed-migrations.sh, its negative-content helper and the workflow/test fixtures that invoke it.
Implementation Sequence
- Define total scanner-status handling and declared coverage.
- Add missing-command, scanner-error, missing-input and actual-leak regressions.
- Apply the smallest proof-only fix.
- Run focused cases and the complete existing proof, then independent review on the final SHA.
Execution mode: implementation
Depends on: none
Bug Summary
scripts/test-install-managed-migrations.shusesrgfor its final secret-leak assertion, but does not distinguish “no match” from “command unavailable”. In the current GitHub Actions environment, the script emittedrg: command not foundand then still printed its PASS line.This creates a false-green CI security assertion: exit status 127 from a missing
rgbinary is treated by the shellifexactly like a normal non-match.Current Behaviour
The final assertion is equivalent to:
Observed in Web CI while reviewing PR #361:
Expected Behaviour
The proof must fail closed if its search dependency is unavailable, or use a guaranteed/fallback search mechanism. “Tool missing” must never be interpreted as “secret absent”.
Recommended Remediation
Preflight the declared scanner dependency and handle its actual exit status explicitly: match means leak/assertion failure; documented no-match with no error may continue; missing command, unreadable input, invalid invocation, signal or any other error fails the proof. Preflight alone is insufficient. Apply the same total-status handling to the script's negative-content assertion helper.
Keep fixed-string/option-safe arguments, bounded fixture scope and explicit allowed environment-file exclusions. Test missing/error paths executablely, not just by checking source text. Full architecture and regression matrix: #362 (comment)
Scope
This is independent of #354 / PR #361’s readiness-control-plane code and should be fixed separately so it does not reset that PR’s final-source review gate.
Reproduction Steps
Impact
The managed-migration security proof can report success without completing its secret-leak/negative-content assertions. This weakens CI evidence; it does not establish that a real production secret leaked.
Severity
P1 / high proof-integrity defect.
Acceptance Criteria
Primary Code Seams
scripts/test-install-managed-migrations.sh, its negative-content helper and the workflow/test fixtures that invoke it.
Implementation Sequence