journal(redfix): wake #19 — consumed review(redfix)@2ad38f5 (re-confirmation #17); my B-redfix-7 severity rationale was wrong on the axis ("no non-root login users" — but mode 644 lets any uid read; setpriv --reuid=1000 succeeds). Re-derived the correct containment first-hand rather than inheriting it: mount-namespace isolation (only dbus-daemon uid 4 shares pid1's mnt-ns; the uid-1000 warm-keycloak JVM is in ns 4026533305 and cannot see host /etc). Same LOW severity, different load-bearing reason — and a fragile one, so the case to fix strengthens. Corrected the bullet, cross-ref A-redfix-1; no verdict change, DONE stands, loop remains stopped
This commit is contained in:
@ -87,10 +87,19 @@ hold). Concrete fix designs from M1 evidence:
|
||||
- `/etc/cc-ci/.git/config` is mode **644** `root:root` and its `origin` URL embeds
|
||||
`https://autonomic-bot:<password>@git.autonomic.zone/...` — the bot's Gitea credential at rest in
|
||||
cleartext. (Value deliberately not reproduced here.)
|
||||
- **Severity is LOW, not nil:** `awk` over `/etc/passwd` shows **no non-root login users** (no uid>=1000
|
||||
with a real shell), so today only root can read it. It is defence-in-depth that is missing, not a live
|
||||
compromise. It would become real the moment any unprivileged user or a container bind-mounting `/etc`
|
||||
exists.
|
||||
- **Severity is LOW, not nil — but my first rationale for that was WRONG** (corrected wake #19 after
|
||||
Adversary re-confirmation #17; filed Adversary-side as **A-redfix-1**). I originally argued "no
|
||||
non-root *login* users, so only root can read it." That is the wrong axis: a process needs no login
|
||||
shell to run as uid 1000, and mode 644 permits **any** uid to read. Verified directly —
|
||||
`setpriv --reuid=1000 … /etc/cc-ci/.git/config` **succeeds** in the host namespace.
|
||||
- **What actually contains the blast radius is mount-namespace isolation**, re-derived first-hand:
|
||||
exactly ONE non-root process shares pid1's mount ns (`dbus-daemon`, uid 4). Every other non-root
|
||||
process is containerized — notably the uid-1000 Quarkus `java` that IS the internet-facing
|
||||
warm-keycloak: its `ns/mnt` is `4026533305` vs pid1's `4026531841`, and
|
||||
`ls /proc/<pid>/root/etc/cc-ci` → **No such file or directory**. Mode-permits ≠ reachable.
|
||||
- **Therefore the containment is load-bearing on a fragile property** and dies silently if a non-root
|
||||
host-namespace daemon ever appears, or if `/etc` is bind-mounted into any container. That fragility —
|
||||
not the current reachability — is the reason to fix it.
|
||||
- `/etc/cc-ci` is a **real directory, not a `/nix/store` symlink**, and **no systemd unit references
|
||||
it** — i.e. undeclared, unmanaged server state that nothing runs from. It violates the standing
|
||||
"keep server state Nix-declared and reversible" rule.
|
||||
|
||||
@ -1176,3 +1176,42 @@ fixed and verified.
|
||||
|
||||
Node untouched: every command this wake was read-only (`git -C … rev-parse/cat-file/symbolic-ref`, `stat`,
|
||||
`awk`, `readlink`). Nothing claimed. DONE stands.
|
||||
|
||||
## Wake #19 — 2026-07-09T02:08Z — consumed review(redfix)@14c7dee (re-confirmation #17); my B-redfix-7 severity rationale was WRONG on the axis; corrected after re-deriving the Adversary's replacement
|
||||
|
||||
Consumed re-confirmation #17 (`14c7dee`). It accepted my `/etc/cc-ci` correction (after re-deriving it
|
||||
rather than taking it on trust), confirmed B-redfix-7 as real + LOW, filed it Adversary-side as
|
||||
**A-redfix-1** — and **corrected my reasoning**, which was wrong. No finding, no VETO, DONE stands, loop
|
||||
stays stopped.
|
||||
|
||||
**Where I was wrong.** I justified "severity LOW" with *"no non-root login users, so only root can read it."*
|
||||
That reasons about the wrong thing. A process does not need a login shell to run as uid 1000, and mode 644
|
||||
lets any uid read the file regardless. I did not accept the Adversary's replacement on trust either — the
|
||||
whole point of this exchange is that neither of us inherits a fact. Re-derived all three legs myself:
|
||||
|
||||
setpriv --reuid=1000 --clear-groups … /etc/cc-ci/.git/config → SUCCEEDS ⇒ my premise was false
|
||||
non-root procs sharing pid1's mnt-ns (4026531841) → exactly 1: dbus-daemon, uid 4
|
||||
uid-1000 quarkus java (the live warm-keycloak), pid 2327794 → mnt-ns 4026533305 ≠ host
|
||||
ls /proc/2327794/root/etc/cc-ci → No such file or directory
|
||||
|
||||
So the credential is contained by **mount-namespace isolation**, not by the absence of login accounts. Same
|
||||
LOW verdict, entirely different load-bearing reason. Rewrote the B-redfix-7 severity bullet accordingly and
|
||||
cross-referenced A-redfix-1; the remedy ladder is unchanged.
|
||||
|
||||
**Why the distinction matters rather than being pedantry.** "No non-root users" reads as a static fact about
|
||||
the box. Mount-namespace containment is a *fragile* property: it evaporates the moment a non-root host-ns
|
||||
daemon appears, or `/etc` is bind-mounted into any container. My wrong rationale would have made the risk
|
||||
look permanently dormant; the true one shows it is one config change away from live. That is now the stated
|
||||
reason to fix it, and it strengthens rather than weakens the case for the operator to act.
|
||||
|
||||
Also noted: the Adversary recorded a near-miss against itself — its `setpriv` probe ran in the *host* ns, so
|
||||
it nearly concluded "internet-facing Keycloak can exfiltrate the bot credential," which is false. Its own
|
||||
tally is that two of its last three probes gave plausible answers for invalid reasons, both caught by
|
||||
re-running the probe against the thing it claimed to measure rather than by re-checking the conclusion. Mine
|
||||
this wake was the same class of error, caught the same way. Worth carrying forward: verifying a *conclusion*
|
||||
is nearly worthless; verifying that the *probe measures what it purports to* is what catches these.
|
||||
|
||||
Scope unchanged: A-redfix-1 / B-redfix-7 is pre-existing infra state, touches no DoD item, and the credential
|
||||
is a Class-A1 external input — the operator's to rotate. **The phase is not reopened.** All commands this
|
||||
wake were read-only (`readlink`, `pgrep`, `ls /proc/…`, and a zero-byte `head -c 0` for the mode check).
|
||||
Nothing claimed. DONE stands.
|
||||
|
||||
Reference in New Issue
Block a user