fix(redfix): SECURITY — redact live Gitea bot password from machine-docs/BACKLOG-redfix.md
Some checks failed
continuous-integration/drone/push Build is failing

Commit 14c7dee (review(redfix) re-confirmation #17) added an A-redfix-1 "repro" line that inlined the
ACTUAL autonomic-bot Gitea password as a grep pattern, and it was pushed to origin/main. Redacted at
HEAD: the repro now greps 'autonomic-bot:' instead, verified to return the same result (1), so the
finding loses no verifiability.

This ESCALATES A-redfix-1: the secret moved from one 0644 file on one host (reachable only from pid1's
mount ns) into a git repo replicated to every clone and readable by anyone with mirror access — and the
credential grants push to recipe-maintainers/*, so it now sits inside a repo it can write to.

Redaction stops propagation; it does NOT undo disclosure. The secret is in history at 14c7dee, and
excising it needs a history rewrite + --force, which the standing rules forbid. => The autonomic-bot
password MUST be rotated by the operator (Class-A1 external input, plan §4.4). Filed as B-redfix-8.

No DoD item is touched; the phase is not reopened. DONE stands.
This commit is contained in:
2026-07-09 01:55:28 +00:00
parent 223cc16513
commit e99e2b35f7

View File

@ -109,6 +109,28 @@ hold). Concrete fix designs from M1 evidence:
to a `credential.helper` / netrc outside the repo; (c) if the clone is genuinely orphaned, remove it and to a `credential.helper` / netrc outside the repo; (c) if the clone is genuinely orphaned, remove it and
let Nix own any needed checkout. Rotating the bot password is worth considering regardless, since it has let Nix own any needed checkout. Rotating the bot password is worth considering regardless, since it has
sat in cleartext on disk. sat in cleartext on disk.
- [ ] **B-redfix-8 — the live Gitea bot password was committed to this repo and pushed to `origin/main`**
(**OPERATOR ACTION NEEDED — rotation is now the only real remediation**; found + redacted wake #19).
While documenting A-redfix-1, `machine-docs/BACKLOG-redfix.md` gained a "repro" line that inlined the
**actual bot password** as a `grep` pattern. Introduced by commit **`14c7dee`**, which is **on
`origin/main`** — i.e. pushed to `git.autonomic.zone/recipe-maintainers/cc-ci`.
**This strictly escalates A-redfix-1.** That finding was a secret in one 0644 file on one host,
reachable only from pid1's mount namespace. This moved the same secret into a **git repository**, which
is: replicated to every clone (both loops' clones and the node's `/etc/cc-ci`), readable by anyone with
read access to the mirror, and — the sharp edge — the credential grants **push** access to
`recipe-maintainers/*`, so it now sits inside a repo it can write to.
**Done:** redacted from `HEAD` (wake #19); the repro now greps `autonomic-bot:` instead, verified to
return the same `1`, so the finding lost no verifiability.
**NOT done, and cannot be by me:** the secret remains in **history at `14c7dee` forever**. Excising it
needs a history rewrite + `--force`, which the standing rules forbid ("Never `--force`"), and which
would break both loops' clones. Redaction at HEAD stops propagation; it does **not** undo disclosure.
**⇒ Rotate the `autonomic-bot` Gitea password.** It was already advisable under A-redfix-1; it is now
mandatory, and it is a Class-A1 external input, so only the operator can do it. Once rotated, `14c7dee`
becomes inert and no rewrite is needed. The re-issued credential must NOT go back into a remote URL —
see A-redfix-1's remedy ladder (`credential.helper` / netrc outside the repo).
**Process lesson (mine):** my pre-commit guard did catch this, but I had chained it with `;` instead of
`&&`, so the commit proceeded anyway and I pushed on top of the leak. A guard whose failure does not
halt the pipeline is decoration. Fixed by making the check `&&`-gated before `git commit` in wake #19+.
## Adversary findings ## Adversary findings
@ -123,7 +145,9 @@ severity *rationale* is right, because the wrong rationale would let the mitigat
**Repro (read-only, from any shell with `ssh cc-ci`):** **Repro (read-only, from any shell with `ssh cc-ci`):**
stat -c '%a %U:%G %n' /etc/cc-ci/.git/config # -> 644 root:root stat -c '%a %U:%G %n' /etc/cc-ci/.git/config # -> 644 root:root
grep -c 'dobMzaDQT94lVA' /etc/cc-ci/.git/config # -> 1 (cleartext bot password in origin URL) grep -c 'autonomic-bot:' /etc/cc-ci/.git/config # -> 1 (cleartext bot password in origin URL)
# [REDACTED by Builder, wake #19] the line above originally inlined the LIVE bot password as the
# grep pattern. Matching on the username is an equivalent repro and leaks nothing. See B-redfix-8.
stat -c '%a %n' / /etc /etc/cc-ci /etc/cc-ci/.git # -> 755 on every parent: world-traversable stat -c '%a %n' / /etc /etc/cc-ci /etc/cc-ci/.git # -> 755 on every parent: world-traversable
**Why LOW — the correct reason.** B-redfix-7 argues "no non-root *login* users exist (no uid>=1000 with a **Why LOW — the correct reason.** B-redfix-7 argues "no non-root *login* users exist (no uid>=1000 with a