tools/redact_trial.py reads stdin and writes stdout, opening no path (SonarCloud S2083, S8707)
Merged
DO
5d ago+122+122+012345678901234567890123456789-37-37-01234567890123456789
SonarCloud has two findings open on main against tools/redact_trial.py: S2083 (path injection) and S8707. The tool opened the two paths it was given. As #273 did for its drift comparer, it now opens no path at all:
- Standard input carries the raw capture in.
- Standard output carries what is left out, written as UTF-8 whatever the locale.
- Standard error names each removal, by where it was and never what it held.
- Any argument is refused before anything is read.
It still runs as python3 -m tools.redact_trial from the repo, since it reads tools/check_trials.py's rules. So it cannot run as python3 -I, which would drop the repo from its path.
Callers
Every call moves from redact_trial RAW OUT > REPORT to redact_trial < RAW > OUT 2> REPORT:
- the trial scripts of P-4, P-8, P-13 and P-39;
- the App's script,
tools/trial_as_app.sh, which sends the report through its pipe:< "$1" 2>&1 > clean | sed; tools/rulesets_drift.sh;- the skill's step 4, and P-13's runbook.
The three calls that discard the report say so and stop when the redaction fails.
P-26's script, on its own branch, makes the same change when it next merges main.
Behaviour kept
- Line ends. CR LF and a lone CR are read as a line's end, as the old read from a file did.
gh api --includeends its head's lines with CR LF. Read as bytes without this, a head would be redacted as body. This was the review's blocker. - Encoding. Bytes that are not UTF-8 stop it, with nothing written, as before.
Tests and mutants
Redaction.test_it_opens_no_path_it_is_givencovers:- each argument refused before a byte is read;
- a run through pipes, as the scripts run it;
- a CR LF head;
- bytes that are not UTF-8;
- an ASCII locale;
- the App script's redirection order.
- The rulesets drift stand-in now answers with CR LF heads, as
ghdoes. - Three new mutants are killed: the tool reading a path it is given, keeping CR LF, and writing in the locale's encoding. The two older mutants of the redaction still are.
Verification and review
make verifypassed in the worktree, with history, atSIM_SEEDS=40: 889 tests. The scripts' stand-in tests run the real redaction through the new calls.- A fresh Claude review with a security pass on 7e21663 found one blocker (CR LF), two majors (the locale's encoding, failures made silent) and five minors. All are fixed in the fix round, except two minors:
- an empty clean file can be left when the tool fails, which holds nothing;
- the flush is untested.
- Muse: not run (the Maintainer, 2026-10-20: Kernel/hook only).
🤖 Generated with Claude Code
Summary by CodeRabbit
-
New Features
- Redaction now processes trial captures through standard input and output, simplifying integration with command-line workflows.
- Cleaned captures continue to remove credentials, sensitive headers, and credential-like content.
- Redaction diagnostics are reported separately from cleaned output.
-
Bug Fixes
- Line-ending handling is now consistent across input formats.
- Output is always encoded as UTF-8.
- Redaction failures now produce clear errors and stop affected trial workflows safely.