Record the 2026-08-20 ruling: OpenBao layer, id collision, silent-drop defect
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
42bbf5d2dc
commit
c73848250c
1 changed files with 95 additions and 0 deletions
95
docs/rulings/2026-08-20-openbao-layer.md
Normal file
95
docs/rulings/2026-08-20-openbao-layer.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
---
|
||||
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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue