docs(security): prove the delivery path on hardware; close window 15
Controlled test on archi-dev-box with operator approval. The daemon was
stopped first so the reconciler could not repair the state before the
re-exposure was confirmed — without a confirmed 200, the later 401 would
be consistent with the state never having been broken at all.
1. stale conf installed + container restarted -> POST /bitcoin-rpc/
returned 200 with a real block height and Allow-Origin: *
2. daemon started 20:00:36, nothing else touched
3. 20:02:19 reconcile rendered the conf and logged the expected warn
line naming bitcoin-ui/archy-bitcoin-ui, then restarted it
4. POST -> 401, Allow-Origin origin-scoped
5. conf byte-identical to the pre-test known-good, container healthy
Both halves are now proven on real hardware: a05956c4's template (the
gate works) and f6b5245b's delivery path (the gate reaches a container
the reconciler had been skipping).
Also records the operator's decision AGAINST credential rotation — no
macaroon, no Bitcoin RPC password — with the trade it accepts stated
plainly, so it is not silently re-litigated later.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
186a2c36c8
commit
e205f2c34a
@@ -100,8 +100,48 @@ rounded off: `bitcoin-ui` is *still* in the node's `user-uninstalled` marker, me
|
||||
next time its config needs to change, this node depends on `f6b5245b` — untested — or on
|
||||
someone happening to rebuild the app again.
|
||||
|
||||
Tracked as broken window 15. Closing it needs a node whose `bitcoin-ui` conf is still
|
||||
stale, or a deliberately re-staled one.
|
||||
Tracked as broken window 15 — **since closed by the controlled test below.**
|
||||
|
||||
## Proving the delivery path on real hardware
|
||||
|
||||
Run on archi-dev-box, 2026-08-02 20:00–20:03 EDT, with operator approval. The point was to
|
||||
prove the thing the incidental rebuild had made unprovable: that **reconcile itself**
|
||||
repairs this state, unaided.
|
||||
|
||||
The daemon was stopped first, so the reconciler could not repair the state before the
|
||||
re-exposure had been confirmed — otherwise a passing probe would prove nothing about
|
||||
which mechanism produced it.
|
||||
|
||||
| Step | Action | Observed |
|
||||
|---|---|---|
|
||||
| 1 | Install a faithfully stale conf (no `auth_request`, credential-injecting `proxy_pass`, `Allow-Origin: *`) and restart the container | — |
|
||||
| 2 | Probe with no cookies | `POST /bitcoin-rpc/` → **`200`**, `{"result":960790}`; `Allow-Origin: *`. **Genuinely re-exposed** |
|
||||
| 3 | Start the daemon (20:00:36) and touch nothing further | — |
|
||||
| 4 | Reconcile pass at **20:02:19** | `bitcoin_ui: nginx.conf rendered auth_hash=51f2b5af`, then `WARN prod_orchestrator: rewrote config for a user-uninstalled app whose container is still RUNNING (systemd/Quadlet keeps it alive independently of reconcile) — restarting so it picks the new config up app_id=bitcoin-ui container=archy-bitcoin-ui` |
|
||||
| 5 | Probe again | `POST /bitcoin-rpc/` → **`401`**; `Allow-Origin: http://192.168.63.240:8334` |
|
||||
| 6 | Compare state | Conf **byte-identical** to the pre-test known-good; container healthy |
|
||||
|
||||
Step 2 is what makes steps 4–6 mean anything: without a confirmed `200`, the later `401`
|
||||
would be consistent with the state never having been broken at all.
|
||||
|
||||
Both halves are now proven on hardware: `a05956c4`'s template (the gate works) and
|
||||
`f6b5245b`'s delivery path (the gate arrives at a container the reconciler had been
|
||||
skipping).
|
||||
|
||||
## Credential rotation — decided against, 2026-08-02
|
||||
|
||||
The operator's call, recorded here so it is not silently re-litigated: **no LND macaroon
|
||||
rotation, and no Bitcoin RPC password rotation.** The reasoning was that there is no
|
||||
evidence of exploitation and the vulnerability is being closed rather than lived with.
|
||||
|
||||
`scripts/security/rotate-lnd-macaroon.sh` stays in the tree as a tool. It has been
|
||||
exercised in detect mode only, and has never rotated anything on any node. Its ordering
|
||||
guard (refuses to rotate on a binary lacking the fix) remains the right shape for whenever
|
||||
rotation is wanted — including for the Bitcoin RPC password, which has no equivalent tool
|
||||
yet.
|
||||
|
||||
What this decision accepts: any macaroon or RPC password read through either hole before
|
||||
it was closed stays valid. That is a deliberate, informed trade, not an oversight.
|
||||
|
||||
## Operator note
|
||||
|
||||
|
||||
Reference in New Issue
Block a user