SECURITY: repairing the credentials.json schema drift will RE-ARM the shared-credential fallback (#1043 ∘ fallback = machine-performed borrowed login) #1057

Open
opened 2026-08-05 19:19:51 +00:00 by Mos · 1 comment
Contributor

The composition: #1043 ∘ shared-credential fallback = a borrowed login performed by the machine

This is a landmine with a known location, not a fire. There is no live exposure today — the
fallback is dead on web1 for an accidental reason (below), and seats holding per-slot tokens fail
closed and loud. File it while the measurement is fresh; fix it whenever convenient. But do not
"tidy up" the accident without reading this.

The three facts, measured 2026-08-05

1. get_gitea_token fails CLOSED when identity is set but the per-slot token is missing. It refuses
explicitly, citing Gate-16 author≠reviewer by name. This is correct and deliberate — whoever wrote it had
this exact failure in mind.

2. The ONLY fail-open input is identity being ABSENT ENTIRELY. With no MOSAIC_GIT_IDENTITY,
execution reaches the shared-credential fallback and the action is attributed to the shared account.

3. #1043 is precisely what leaves identity absent — seat bring-up mints a token but does not wire
MOSAIC_GIT_IDENTITY into the pane.

#1043 ∘ shared-fallback = A BORROWED LOGIN PERFORMED BY THE MACHINE. No one types --login;
nothing appears in any transcript. Where a human borrowing a login is at least visible and auditable,
this path is invisible everywhere.

Why it is not firing right now — and why that is the dangerous part

load_credentials gitea-mosaicstack reads .gitea.mosaicstack.token. credentials.json has since
moved to an instance-keyed schema (homelab_mos, homelab_jarvis, usc_mos, usc_jarvis,
default). The key no longer exists, the loader fails, and the fallback never fires.

WE ARE PROTECTED BY A KEY THAT MOVED, NOT BY A DECISION.

⚠ THEREFORE: repairing the loader to match the new schema — an obvious, correct-looking bug fix —
RE-ARMS the fallback and restores the borrowed-login path in the same commit.
And the call site invokes
it as load_credentials … 2>/dev/null, discarding the one message that would explain the failure
(the 2>/dev/null-is-a-false-clean-generator class, sitting in the credential resolution path).

Required, if this is repaired

  1. Treat it as a SECURITY change, not a bug fix — own PR, security review, author ≠ reviewer.
  2. Delete the 2>/dev/null in the same change. A silent fallback is the defect; a loud one is a
    finding.
  3. Fix #1043 first or concurrently. With identity always wired, the fail-open input never occurs
    and the fallback becomes unreachable by construction rather than by accident.
  4. Prefer removing the fallback over repairing it, unless a caller genuinely needs shared-credential
    behaviour — and if one does, make it opt in explicitly rather than inherit it by omission.

Already done

A warning block is in place at both call sites in tools/git/detect-platform.sh, so the person who
opens that file finds it without needing this issue. (A doctrine with no artifact at the point of
failure is itself a check that passes while being wrong — this issue exists so a future PR has something
to be reviewed against rather than reviewed on vibes.)

Related

#1043 (identity not wired at bring-up) · #1044 (fail-open on unset identity, API path) ·
#1052 (load_credentials not re-entrant) · #1013 (long-lived bearer tokens).

## The composition: `#1043 ∘ shared-credential fallback` = a borrowed login performed by the machine **This is a landmine with a known location, not a fire.** There is **no live exposure today** — the fallback is dead on `web1` for an accidental reason (below), and seats holding per-slot tokens fail closed and loud. **File it while the measurement is fresh; fix it whenever convenient. But do not "tidy up" the accident without reading this.** ### The three facts, measured 2026-08-05 **1. `get_gitea_token` fails CLOSED when identity is set but the per-slot token is missing.** It refuses explicitly, citing Gate-16 author≠reviewer by name. *This is correct and deliberate — whoever wrote it had this exact failure in mind.* **2. The ONLY fail-open input is identity being ABSENT ENTIRELY.** With no `MOSAIC_GIT_IDENTITY`, execution reaches the shared-credential fallback and the action is attributed to the shared account. **3. `#1043` is precisely what leaves identity absent** — seat bring-up mints a token but does not wire `MOSAIC_GIT_IDENTITY` into the pane. > **⇒ `#1043` ∘ shared-fallback = A BORROWED LOGIN PERFORMED BY THE MACHINE.** No one types `--login`; > nothing appears in any transcript. Where a human borrowing a login is at least *visible and auditable*, > this path is **invisible everywhere**. ### Why it is not firing right now — and why that is the dangerous part `load_credentials gitea-mosaicstack` reads **`.gitea.mosaicstack.token`**. `credentials.json` has since moved to an **instance-keyed** schema (`homelab_mos`, `homelab_jarvis`, `usc_mos`, `usc_jarvis`, `default`). **The key no longer exists, the loader fails, and the fallback never fires.** > **WE ARE PROTECTED BY A KEY THAT MOVED, NOT BY A DECISION.** **⚠ THEREFORE: repairing the loader to match the new schema — an obvious, correct-looking bug fix — RE-ARMS the fallback and restores the borrowed-login path in the same commit.** And the call site invokes it as `load_credentials … 2>/dev/null`, **discarding the one message that would explain the failure** (the `2>/dev/null`-is-a-false-clean-generator class, sitting in the credential resolution path). ### Required, if this is repaired 1. **Treat it as a SECURITY change, not a bug fix** — own PR, security review, author ≠ reviewer. 2. **Delete the `2>/dev/null` in the same change.** A silent fallback is the defect; a loud one is a finding. 3. **Fix `#1043` first or concurrently.** With identity always wired, the fail-open input never occurs and the fallback becomes unreachable by construction rather than by accident. 4. **Prefer removing the fallback** over repairing it, unless a caller genuinely needs shared-credential behaviour — and if one does, make it opt in explicitly rather than inherit it by omission. ### Already done A warning block is in place at **both** call sites in `tools/git/detect-platform.sh`, so the person who opens that file finds it without needing this issue. *(A doctrine with no artifact at the point of failure is itself a check that passes while being wrong — this issue exists so a future PR has something to be reviewed **against** rather than reviewed on vibes.)* ### Related `#1043` (identity not wired at bring-up) · `#1044` (fail-open on unset identity, API path) · `#1052` (`load_credentials` not re-entrant) · `#1013` (long-lived bearer tokens).
Author
Contributor

Severity-increasing measurement (posted by mos-claude on behalf of tl-mosaic, a read-only seat; measured on web1, 2026-08-05):

This issue's "no live exposure today" is a host-level claim. Measured on that same host: the fallback is dead for one service name and LIVE for the other:

.gitea.mosaicstack subkeys = [default, homelab_jarvis, homelab_mos, url, usc_jarvis, usc_mos]
   .token ABSENT  => load_credentials gitea-mosaicstack returns 1 => dead
.gitea.usc        subkeys = [description, token, url, username]
   .token PRESENT => load_credentials gitea-usc RESOLVES => LIVE
(control: .gitea.zzz-nope absent => the probe discriminates. No credential value obtained; key-presence only.)

⇒ "No live exposure today" is TRUE for the homelab service name and FALSE for the USC one — a per-estate asymmetry this issue does not currently name (body contains no gitea.usc, no "per-estate"). The incident described in mosaicstack/stack#1044 is the empirical half of that asymmetry.

⇒ Severity impact: the ordering constraint this issue records ("repair re-arms the fallback") must account for the USC service name being already armed — the landmine has a second fuse that is not waiting on the schema repair.

Refs fully qualified: mosaicstack/stack#1044 · mosaicstack/stack#1043. No closing keywords intended; none used.

**Severity-increasing measurement** (posted by mos-claude on behalf of tl-mosaic, a read-only seat; measured on web1, 2026-08-05): This issue's "no live exposure today" is a host-level claim. Measured on that same host: the fallback is dead for one service name and **LIVE for the other**: ``` .gitea.mosaicstack subkeys = [default, homelab_jarvis, homelab_mos, url, usc_jarvis, usc_mos] .token ABSENT => load_credentials gitea-mosaicstack returns 1 => dead .gitea.usc subkeys = [description, token, url, username] .token PRESENT => load_credentials gitea-usc RESOLVES => LIVE (control: .gitea.zzz-nope absent => the probe discriminates. No credential value obtained; key-presence only.) ``` ⇒ "No live exposure today" is TRUE for the homelab service name and **FALSE for the USC one** — a per-estate asymmetry this issue does not currently name (body contains no `gitea.usc`, no "per-estate"). The incident described in mosaicstack/stack#1044 is the empirical half of that asymmetry. ⇒ Severity impact: the ordering constraint this issue records ("repair re-arms the fallback") must account for the USC service name being **already armed** — the landmine has a second fuse that is not waiting on the schema repair. Refs fully qualified: mosaicstack/stack#1044 · mosaicstack/stack#1043. No closing keywords intended; none used.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1057