--- 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`.