fix(pipeline-doctor): accept pass-var token form + exempt --password-stdin from leak scan (#199)

The audit sweep wrongly FAILED ~9 converted ci-script repos on two heuristics:
- token-contract now accepts the secure indirection pass "$PASS_ENTRY" /
  pass "$VAR", not only a hard-coded pass <literal-path>.
- leak scan flattens \-continuations + folds the pipe target onto the echo
  line, then exempts the echo "$TOKEN" | <cmd> ... --password-stdin/--pass-stdin
  stdin-feed idiom; bare echo to stdout/file and set -x still FAIL.
Adds --self-test with six inline fixtures locking in both fixes and the
three must-still-catch leaks.
This commit is contained in:
Oleks
2026-06-03 10:42:26 +03:00
parent db0bf3b9ab
commit d265a79ddb
2 changed files with 107 additions and 8 deletions
+18
View File
@@ -7,6 +7,24 @@ semantic versioning; the version is a conceptual tag (no git tag is created).
## Unreleased
- **Fix: `pipeline-doctor` token-heuristic false positives (#199).** The audit
sweep wrongly FAILED ~9 correctly-converted ci-script repos on two heuristics.
(1) The token-contract check only accepted a hard-coded `pass <literal-path>`;
it now also accepts the secure indirection `pass "$PASS_ENTRY"` / `pass "$VAR"`
(a quoted/unquoted shell var, optionally via `pass show`). (2) The leak scan
flagged the blessed `echo "$TOKEN" | docker login … --password-stdin` (and
`--pass-stdin`, and helm `registry login`) idiom — the token goes to STDIN, not
the log — because the `--password-stdin` flag often sits on a `\`-wrapped
continuation line the line-based grep never saw on the `echo` line. The scan now
flattens `\`-continuations and folds the pipe target onto the `echo` line, then
exempts the `… | <cmd> … --password-stdin`/`--pass-stdin` feed. Real leaks still
FAIL: a bare `echo "$TOKEN"` to stdout or a file, and `set -x` in a token script.
Added `--self-test`: six inline fixtures lock in both fixes and the three
must-still-catch leaks. Verified: version-radar, xonsh, common-chronicle,
ii-researcher, ironclaw, openclaw now PASS; parity-lib `--strict .`, gitea-mcp,
numpy-s390x still 9/9. (commonground-legacy / cms-plugins / csi-s3 still FAIL one
UNRELATED check — dev-tag-guard — because their woodpecker config lives in a
`.woodpecker/` directory the doctor doesn't yet read; out of scope for #199.)
- **Feature: `mkAtticClosurePublish` — the attic-closure builder (cluster #198).**
Models the archetype parity-lib was missing: build a Nix closure and push it to
the Attic binary cache (NO registry artifact). Yields `stage-<arch>` (`nix build`