risk-nexus/docs/rulings/2026-08-19-first-grading.md
tegwick d5a3953f2e RISK-WP-0001 T01-T06,T08: the four instruments, the index, and the first grading
Severity (impact x likelihood, fidelity modifier for controls that lie,
headline-vs-constraint, build-mode double grade, the floor), disclosure
(publish/embargoed/restricted, and the build-mode deferral re-taken and
narrowed with RISK-F-0001 in hand), escalation (the five INTENT triggers
settled plus an ordering-hazard trigger the RISK-F-0002 case forced;
proposed, awaiting the custodian), review (intervals, what a review is,
what missing one produces, the production re-score).

Then applied: RISK-F-0001 critical/embargoed/escalated, RISK-F-0002
medium with a high constraint on RISK-F-0001's remediation, filed as a
peer and escalated only on the ordering, RISK-F-0003 high/embargoed/no
escalation. No unset field remains.

REGISTER.md is generated; make check reports overdue, stalled, ungraded
and unanswered escalations without changing anything.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 23:29:39 +02:00

225 lines
10 KiB
Markdown

---
id: RISK-RULING-2026-08-19
type: ruling
title: "First grading: RISK-F-0001, RISK-F-0002, RISK-F-0003"
status: recorded
owner: risk-nexus
date: "2026-08-19"
workplan: RISK-WP-0001-T06
---
# First grading — 2026-08-19
The first application of `docs/method/`. Three findings, graded together
because the instruments were written for them and a scale that has never been
used is a draft.
Where a grading changed what an owning repo should do, it went back as a
message. No owning repo's files were edited.
## RISK-F-0001 — flex-auth /v1/check authenticates no caller
| Field | Value |
| --- | --- |
| Impact | `I4` |
| Likelihood | `L3` |
| Fidelity modifier | no |
| **Severity** | **critical** |
| At production | critical |
| Disclosure | embargoed |
| Escalation | yes — trigger 1 |
| Review by | 2026-08-26 |
**Impact `I4`.** `flex-auth` is the estate's authorization oracle. A forged
allow does not stay in `flex-auth`; it is the answer other services act on,
and `tenant-engine` has separately stated that direct authority over its rows
means privilege escalation across NetKingdom rather than tampering confined to
one store. That is the definition of `I4` — what is compromised here
propagates to everything that trusts it.
**Likelihood `L3`, not `L4`.** Any workload with cluster reach can assert any
subject and any tenant. That is the normal working set with no additional
step. It is not `L4` only because reach is inside the cluster rather than open.
The register follows the reporter in **not** assuming a default-deny
NetworkPolicy exists, and equally in not assuming its absence proves wider
exposure. `flex-auth` did not state it either way. This is the single fact
that would most change the grade, so it is the first question at review — see
"Asks" below.
**No fidelity modifier.** The endpoint answers honestly about a caller it
never checked; it makes no attestation of its own. The false-record hazard
belongs to `RISK-F-0002`'s constraint, where a *consumer* of this endpoint
would start signing records that assert an authorization was made.
**Production.** Unchanged. Impact is already estate-wide and likelihood does
not depend on there being users.
**Disclosure: embargoed** until `FLEX-WP-0015-T02` ships to production. This
is the finding that forced the deferral to be re-taken
(`docs/method/disclosure.md`): it names an unauthenticated decision surface
and the service carrying it, which shortens the path for exactly one kind of
reader. Publish on fix.
**Escalation: yes, trigger 1.** `INTENT.md` asked whether governing access to
tenant data counts as exposing it. Ruled: it does. An authorization oracle
that can be forged is not one step removed from the data, it is the step.
**Nothing further is asked of `flex-auth`.** They own it, classify it as their
only urgent follow-up, and are shipping through staged promotion.
## RISK-F-0002 — ops-warden signs SSH certificates with no authorization decision
| Field | Value |
| --- | --- |
| Impact | `I3` |
| Likelihood | `L2` |
| Fidelity modifier | no (headline) |
| **Severity** | **medium** |
| Constraint severity | **high** |
| At production | medium |
| Disclosure | embargoed |
| Escalation | via trigger 6 only, jointly with RISK-F-0001 |
| Review by | 2026-11-17 |
`RISK-F-0002` asked this repo three questions. All three are answered here.
### 1. Severity — which state is scored
The headline scores **today**: the gate is off, and that is a missing control
honestly represented. `I3` — SSH certificates into production hosts cross a
trust boundary. `L2` — the caller must already hold a scoped `VAULT_TOKEN` and
the actor must exist in `inventory.yaml`; TTLs are enforced and every issuance
is logged. Possession of the signing token is the whole authorization model,
which is thin, but it is not nothing and it is not `L3`.
**The reporter's argument is accepted in full**: the two states are not equally
bad, and the second is the one worth a severity. It is recorded as a
constraint, not as the headline, because the register describes the estate as
it is and the second state does not exist yet.
> **Constraint (severity `high`).** Enabling `policy.enabled` while
> `flex-auth`'s `/v1/check` answers unauthenticated callers converts an absent
> control into a false attestation: an attacker with ClusterIP reach obtains a
> genuine `allow`, and the signature log carries a `policy_decision_id`
> asserting the issuance was authorized. `I3 + fidelity → I4`, `L2` → `high`.
The constraint attaches to `RISK-F-0001`'s remediation, and the ordering is
recorded on both findings:
```
flex-auth warn-only -> ops-warden gate presents its SA token -> logs clean
-> flex-auth fail-closed -> ops-warden policy.enabled: true
```
The headline being lower than the constraint is exactly the case
`docs/method/severity.md` was written to handle. A reader must not come away
with "medium" and miss the high one.
### 2. Peer or consequence — **peer**
Filed as its own finding, as `ops-warden` filed it. Two reasons, both from
`INTENT.md`'s routing rule: the fix owner differs, and the "off" state has
standing regardless of how `RISK-F-0001` resolves. If `RISK-F-0001` were
withdrawn tomorrow, `ops-warden` would still be signing certificates with no
per-request judgement.
What is *not* independent is the ordering, and that is carried as a constraint
on both rather than by collapsing one finding into the other.
### 3. Escalation — the register disagrees with the reporter, narrowly
`ops-warden` judged this does not need the operator: known, owned, and its
dangerous failure mode written down in both repos. On triggers 1-5 the
register agrees — no real tenant data, no obligation, no spend, no ownership
dispute, no stall.
But the reasoning "it is written down in both repos" is the argument the
register cannot accept on its own, because `RISK-F-0002` is itself the
evidence against it: its own blocker was written down, filed away, and
invalidated in a day with nothing re-checking it. Written down is not the same
as held.
So **trigger 6 fires once** — an ordering hazard whose wrong sequence creates
a false attestation. One acknowledgement from the operator that the ordering
exists, then the register carries it. Not a standing supervision request.
This is the disagreement the escalation rule was worth writing to surface, and
it is the reason trigger 6 exists at all.
**Disclosure: embargoed** until the ordering completes — `FLEX-WP-0015-T02`
shipped *and* `policy.enabled: true` in production. Publishing "production SSH
signing performs no authorization decision" while true shortens the path.
## RISK-F-0003 — agent read-boundary does not fire on ungraded catalog lanes
| Field | Value |
| --- | --- |
| Impact | `I4` |
| Likelihood | `L2` |
| Fidelity modifier | no (see below) |
| **Severity** | **high** |
| At production | high |
| Disclosure | embargoed |
| Escalation | no |
| Review by | 2026-09-18 |
**Impact `I4`, driven by one lane.** Four of the five `exec_capable` ungraded
lanes are `I3`-shaped — a publish token, an OIDC login, an ingestion key, a
hub write token, each bad within its own system. `openbao-api-key` is not:
it vends access to the store the estate's other secrets live in, and a
disclosure there propagates past every boundary the others respect. The
finding is graded on its worst lane.
**Likelihood `L2`.** Requires an agent session with `WARDEN_AGENT_ID` set —
a foothold the estate does grant. `ops-warden` states the exposed population
is not established and should not be assumed zero or large, and the register
holds that line: `L2` is what the stated facts support. The unverified OpenBao
`agent-high-risk-boundary` coverage would lower it if confirmed, and is a
review question rather than an assumption.
**No fidelity modifier, deliberately, and it was close.** `ADR-0004` reads as
a categorical rule while the implementation is an opt-in list, so the estate's
*documentation* asserts a boundary that does not exist for 14 lanes. That is
documentation drift, and the modifier in `docs/method/severity.md` is scoped
to attestations a system produces at runtime. If any compliance evidence
anywhere cites `ADR-0004` as implemented, that is a false attestation and a
separate finding — this register has not looked, and says so rather than
assuming.
**Escalation: no.** Known, owned, tracked (`WARDEN-WP-0032-T05` for the five
lanes, `WARDEN-WP-0032-T06` for the structural fix), and moving. No trigger
fires. Severity alone deliberately does not escalate.
**The operator's maturity-context direction is noted, not re-decided.** The
finding records that an absent grade should resolve from maturity context —
tolerable in early or experimental contexts, `high` or `critical` in
production ones — and that the durable form waits on the zone model
(`ZONE-WP-0001-T03`). The register's only remark is the one the finding
already makes and this repo confirms from its own registration work today:
`.repo-classification.yaml` `category` cannot carry that signal.
`railiance-platform` runs production OpenBao and owns three of the five lanes
while classified `tooling`, and this repo has just classified itself with the
same vocabulary. The maturity ladder needs its own field.
**Disclosure: embargoed** until the five lanes are graded under
`WARDEN-WP-0032-T05`. It names five live lanes that vend real values without
the boundary firing.
## What this grading asks of other repos
Sent as messages, not as edits.
| Repo | Ask |
| --- | --- |
| `flex-auth` | Confirm whether a default-deny NetworkPolicy fronts the `/v1/check` Service. It is the single fact that most changes a `critical` grade, and only they can answer it. |
| `ops-warden` | Confirm the OpenBao `agent-high-risk-boundary` policy's coverage of the five `exec_capable` lanes. |
| both | The ordering constraint is recorded and carried by this register. Neither repo needs to re-derive it. |
## What this grading proved about the instruments
The scale earned two of its features on first use: the fidelity modifier
(needed by `RISK-F-0002`, and correctly *not* applied to `RISK-F-0003`), and
the headline-versus-constraint split (needed the moment a finding described
two states). The floor was not exercised here — all three findings clear it
easily — and gets its real test in `RISK-WP-0001-T07`.