95 lines
4.5 KiB
Markdown
95 lines
4.5 KiB
Markdown
---
|
||
id: RISK-RULING-2026-08-20
|
||
type: ruling
|
||
title: "The OpenBao layer, an id collision, and a status the tooling did not know"
|
||
status: recorded
|
||
owner: risk-nexus
|
||
date: "2026-08-20"
|
||
workplan: RISK-WP-0001-T06
|
||
---
|
||
|
||
# 2026-08-20 — the second ops-warden layer
|
||
|
||
`ops-warden` answered the question this register put to them yesterday, and the
|
||
answer was a finding rather than a yes or no. Three things came out of it: a
|
||
grading, an id collision, and a defect in this repo's own tooling.
|
||
|
||
## RISK-F-0009 — `high`, embargoed, no escalation
|
||
|
||
Filed by `ops-warden` as the OpenBao half of `ADR-0004`. The policy
|
||
`agent-high-risk-boundary` denies 5 data paths, covering 6 of 17 high-risk
|
||
lanes; **8 high-risk lanes have a concrete KV path nothing denies**, reachable
|
||
by a direct `bao kv get` that never touches ops-warden.
|
||
|
||
Graded `I4` × `L2`. `I4` on the worst uncovered lane rather than the average
|
||
one: `scaleway-bootstrap` and `agent-harness-forgejo-deploy` propagate past the
|
||
system holding them. `L2` because it needs an agent token carrying a
|
||
`workload-kv-read-*` policy, which the estate grants.
|
||
|
||
Two limits held rather than resolved, both `ops-warden`'s own: the comparison
|
||
is against the policy **file**, because their operator token is expired
|
||
(`bao token lookup` → 403), so the deployed policy may differ; and whether any
|
||
agent token carries both policies at once is not established.
|
||
|
||
**The finding's most useful sentence is the one that declines credit.** Four of
|
||
the eight uncovered lanes were already `high` before yesterday's regrade, so
|
||
the divergence is pre-existing; the regrade only made the two lists comparable
|
||
enough to see it. A register that let this read as "our work found a new
|
||
defect" would be misreading its own evidence.
|
||
|
||
No escalation: two repos, no disagreement. Trigger 4 needs a *failed* routing
|
||
exchange, and no exchange has failed. Their suggestion — generate the deny set
|
||
from the catalog rather than maintaining two lists — is routed to
|
||
`railiance-platform` as the suggestion it was offered as.
|
||
|
||
## RISK-F-0003 re-checked: `high` → `medium`, and its embargo re-pointed
|
||
|
||
All 17 high-risk lanes now exit 7 on the CLI path. The live gap is closed; the
|
||
omission that allowed it — a lane addable without a grade — is not, and that is
|
||
`WARDEN-WP-0032-T06` plus, durably, the zone model (`RISK-N-0004`). `medium`,
|
||
because "graded by hand once" is not "cannot be ungraded again".
|
||
|
||
Its embargo condition was met and **still did not lift**. The original
|
||
condition was the five lanes being graded; that happened. But `RISK-F-0009`
|
||
shows the second layer still leaves eight lanes reachable by the direct path,
|
||
so publishing `RISK-F-0003` now would name lanes an attacker could still use.
|
||
The condition is re-pointed at `RISK-F-0009`.
|
||
|
||
That is `docs/method/disclosure.md` working across findings rather than within
|
||
one: the test is whether the *text* shortens a path, not whether this
|
||
particular finding's own fix has landed.
|
||
|
||
## The id collision
|
||
|
||
`ops-warden` filed as `RISK-F-0004`. This register had assigned `RISK-F-0004`
|
||
to `tenant-engine`'s unfiltered event read hours earlier, in a commit they had
|
||
not seen. Two findings, one id, both committed.
|
||
|
||
Resolved by the only rule that does not require anyone to have been at fault:
|
||
**earlier commit keeps the id, the newcomer moves.** `RISK-F-0009`, with
|
||
`filed_as: RISK-F-0004` recorded on it so their references remain traceable.
|
||
|
||
The real fix is in `findings/README.md`, which now says how ids are allocated
|
||
and what happens on a clash. The contract had never said, so nobody did
|
||
anything wrong.
|
||
|
||
## The tooling defect, which is the one worth remembering
|
||
|
||
`RISK-F-0003` came back with `status: mitigated` — an accurate word, and one
|
||
this register had never defined. `make check` watched `open` and `accepted`,
|
||
so the finding **silently dropped out of the nag**.
|
||
|
||
A finding disappearing from the register's own watch list because a reporter
|
||
used an unfamiliar word is the exact failure `INTENT.md` names: silence that
|
||
looks like resolution.
|
||
|
||
Two changes:
|
||
|
||
- `mitigated` is now a defined status — the live gap closed, the finding not.
|
||
It was a better word than anything this repo had.
|
||
- **Any unrecognised status keeps the finding watched and gets reported.**
|
||
The watch list is now defined by exclusion — only `fixed` and `withdrawn`
|
||
leave it — so an unknown word can never again quietly remove something.
|
||
|
||
Fail loud, not quiet. The register got this wrong on its second day and found
|
||
it by accident, which is the same way everything else in here has been found.
|