RISK-WP-0001-T07: rule on what was waiting outside the register

Four in as findings — tenant-engine unfiltered event read (high),
audit-core read path bounded by a flag not by code (medium), apps-pg with
no backup at all (high, escalated on spend), and the unverified tenant
boundary itself (high now, critical at production, escalated on
ownership, fix_owner deliberately unset). Two out as notes — noisy
neighbours and erasure-versus-audit, both real, neither changing a
decision this month, both carrying an event to be re-read at.

The round amended the scale twice: build mode lowers impact as well as
likelihood, and non-adversarial findings get their own likelihood
reading. The escalation rule gained a ratio test that distinguishes a
first sweep from steady-state intake, and a batching rule.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-19 23:33:08 +02:00
parent d5a3953f2e
commit 4daff5503f
10 changed files with 612 additions and 15 deletions

View file

@ -0,0 +1,88 @@
---
id: RISK-F-0004
type: finding
title: "tenant-engine events() returns the entire event log unfiltered"
status: open
reported_by: tenant-engine
reported_via: flex-auth
routed_by: risk-nexus
date_reported: "2026-08-17"
date_filed: "2026-08-19"
system: tenant-engine
environment: production
fix_owner: tenant-engine
fix_tracking: unset
related: [RISK-F-0001]
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md
severity: high
severity_at_production: critical
impact: I3
likelihood: L3
fidelity_modifier: false
production_rescore: true
disclosure: embargoed
embargo_condition: "the read path filters by tenant in code"
embargo_since: "2026-08-19"
embargo_review: "2026-09-18"
escalation: none
last_reviewed: "2026-08-19"
review_by: "2026-09-18"
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-19-B
---
# RISK-F-0004 — the tenant event log is readable across tenants
## What is true, as reported
`tenant-engine`'s `events()` returns the entire event log with no tenant
filter. Reported by `tenant-engine` as a live cross-tenant read at `E2` on the
Tenancy Posture E ladder, surfaced in the same review round as `RISK-F-0001`
and recorded inside that finding as visible-but-unfiled.
**This repo has not verified it and does not own the code.** It is filed on the
owning repo's own self-report. `tenant-engine` confirms or corrects it.
## Why it is being filed now
It was held back pending the precedent this register set for what warrants a
record of its own. That precedent now exists (`docs/method/severity.md`), and
"still waiting on the precedent" has stopped being an available answer. This
finding clears the floor on both tests: `tenant-engine` can act, and recording
it changes when they act.
## What is not established
- Whether any caller other than `tenant-engine` itself currently reaches
`events()`.
- What the log contains — whether the rows are metadata or carry tenant
payload. The grade assumes cross-tenant *visibility*, not payload
disclosure, and would rise if it is the latter.
- Whether a fix is tracked anywhere. `fix_tracking` is `unset` and this repo
has asked.
## Register ruling — 2026-08-19
`high` today (`I3` × `L3`), `critical` at production, embargoed until the read
path filters in code, no escalation.
`I3`: a cross-tenant read crosses a tenant boundary inside one system. `L3`:
no additional step is needed by anything that can already call the method, and
the authorization that would otherwise constrain the caller is `RISK-F-0001`,
which authenticates nobody.
`production_rescore: true`. Today the log holds no real counterparty's events,
which lowers what one occurrence costs; it does not lower what the defect is.
At production the same read is `I4` — real tenant data crossing a boundary
that nothing verifies — and the re-score is owed before any production
declaration completes.
No escalation: no real tenant data yet (trigger 1 reads *real*), owned, and
not yet stalled. It becomes an escalation on the day the estate takes real
tenant data, and that is what `production_rescore` is for.
## Reviews
- **2026-08-19** — filed and graded from `RISK-F-0001`'s unfiled list.
Open at review: does `tenant-engine` confirm; is a fix tracked; what does
the log actually contain.

View file

@ -0,0 +1,77 @@
---
id: RISK-F-0005
type: finding
title: "audit-core read path applies no tenant filter; the bound is deployment, not code"
status: open
reported_by: audit-core
reported_via: flex-auth
routed_by: risk-nexus
date_reported: "2026-08-17"
date_filed: "2026-08-19"
system: audit-core
environment: production
fix_owner: audit-core
fix_tracking: AUDIT-WP-0008-T04
related: [RISK-F-0004]
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md
severity: medium
severity_at_production: high
impact: I3
likelihood: L2
fidelity_modifier: false
production_rescore: true
disclosure: embargoed
embargo_condition: "AUDIT-WP-0008-T04 lands a tenant filter in the read path"
embargo_since: "2026-08-19"
embargo_review: "2026-11-17"
escalation: none
last_reviewed: "2026-08-19"
review_by: "2026-11-17"
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-19-B
---
# RISK-F-0005 — the audit read path is bounded by a flag, not by code
## What is true, as reported
`audit-core`'s read path applies no tenant filter. A credential holding
`may_read` can read any tenant's events. The production sender is deployed with
`may_read: false`, so the exposure today is bounded **by deployment
configuration and not by code**. Self-reported in the same review round as
`RISK-F-0001`; tracked by `audit-core` as `AUDIT-WP-0008-T04`.
Not verified by this repo. `audit-core` owns it and confirms or corrects it.
## Why the bound is the finding
A defect held shut by a flag is one edit from open, and the edit does not look
dangerous to whoever makes it — enabling a read credential is an ordinary
operational act. The register carries it because the safety here lives in a
value someone can change without reading this file.
That is also why it is filed separately from `RISK-F-0004` rather than as one
"cross-tenant reads" entry: different owner, different fix, and this one has a
tracked fix already.
## Register ruling — 2026-08-19
`medium` today (`I3` × `L2`), `high` at production, embargoed until
`AUDIT-WP-0008-T04` lands, no escalation.
`I3`: crossing a tenant boundary in the audit store. `L2`: it needs a
credential with `may_read`, which the estate grants somewhere but not to the
production sender. It is not `L3` because the flag is genuinely off today, and
not `L1` because the flag is a deployment value rather than an absent code
path.
`production_rescore: true` for the same reason as `RISK-F-0004`: the audit log
does not hold a real counterparty's events yet.
No escalation. Known, owned, tracked, moving.
## Reviews
- **2026-08-19** — filed and graded from `RISK-F-0001`'s unfiled list.
Open at review: has `AUDIT-WP-0008-T04` moved; is `may_read: false` still
true of every production credential, not only the sender.

View file

@ -0,0 +1,88 @@
---
id: RISK-F-0006
type: finding
title: "apps-pg has no backup configured at all: R0 means no recovery"
status: open
reported_by: railiance-platform
reported_via: flex-auth
routed_by: risk-nexus
date_reported: "2026-08-17"
date_filed: "2026-08-19"
system: railiance-platform
environment: production
fix_owner: railiance-platform
fix_tracking: unset
related: [RISK-F-0001]
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md
severity: high
severity_at_production: critical
impact: I4
likelihood: L2
fidelity_modifier: false
production_rescore: true
disclosure: embargoed
embargo_condition: "a backup exists and a restore has been demonstrated once"
embargo_since: "2026-08-19"
embargo_review: "2026-09-18"
escalation: required
escalation_trigger: 3
escalation_status: pending-operator
last_reviewed: "2026-08-19"
review_by: "2026-09-18"
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-19-B
---
# RISK-F-0006 — the platform database cannot be recovered
## What is true, as reported
`apps-pg` (`railiance-platform`) has no backup configured at all: no
`barmanObjectStore`, no retention policy, and `BestEffort` QoS on the pod.
Reported in the same round as `RISK-F-0001`, whose author noted that `R0` here
means **no recovery**, not merely no erasure policy.
Not verified by this repo. `railiance-platform` owns it.
## Why it is graded highest of the round despite being the least exciting
The other findings in this round are about someone reaching something. This one
is about nothing coming back. There is no attacker in it and no clever step —
an ordinary node failure, a lost volume, a mistaken `DROP`, and the data that
was in `apps-pg` is gone.
`BestEffort` QoS makes the pod the first candidate for eviction under memory
pressure. Eviction alone is an availability event and recoverable. What is not
recoverable is anything that damages the volume, and that is the case with no
answer today.
## Register ruling — 2026-08-19
`high` today (`I4` × `L2`, non-adversarial reading), `critical` at production,
embargoed, and **escalated on trigger 3 (spend)**.
`I4`: `apps-pg` is shared platform infrastructure, so the loss is not confined
to one system, and it is unrecoverable rather than degraded. `L2` on the
non-adversarial reading the scale gained for this finding: irrecoverable loss
needs a volume or corruption event, which is an ordinary failure the estate
has seen the shape of but not an expected weekly occurrence.
`production_rescore: true`: at production this is `L3`, because the surface
area of ordinary operational events grows with real traffic and real operators.
**Escalation, trigger 3.** Object storage for backups is recurring spend that
is not currently committed, and no repo can authorise it for itself. The ask
is narrow: approve a backup target and its cost, or state that the estate
accepts running `apps-pg` with no recovery and for how long. The second is a
legitimate answer in build mode and needs saying out loud rather than
happening by default.
The disclosure condition deliberately includes a demonstrated restore. A
backup nobody has restored from is a claim, not a control — the same class of
error as the gate in `RISK-F-0002`.
## Reviews
- **2026-08-19** — filed and graded from `RISK-F-0001`'s unfiled list.
Open at review: has the spend been ruled on; is a backup configured; has a
restore been demonstrated; does `railiance-platform` track it anywhere.

View file

@ -0,0 +1,99 @@
---
id: RISK-F-0007
type: finding
title: "No consumer's tenant boundary is verified anywhere"
status: open
reported_by: net-kingdom
reported_via: risk-nexus
routed_by: risk-nexus
date_reported: "2026-08-19"
date_filed: "2026-08-19"
system: estate
environment: build
fix_owner: unset
fix_tracking: unset
related: [RISK-F-0004, RISK-F-0005]
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md
severity: high
severity_at_production: critical
impact: I3
likelihood: L3
fidelity_modifier: false
production_rescore: true
disclosure: embargoed
embargo_condition: "a verification exists for at least one consumer boundary"
embargo_since: "2026-08-19"
embargo_review: "2026-09-18"
escalation: required
escalation_trigger: 4
escalation_status: pending-operator
last_reviewed: "2026-08-19"
review_by: "2026-09-18"
graded_by: risk-nexus
ruling: RISK-RULING-2026-08-19-B
---
# RISK-F-0007 — nothing checks that tenants stay apart
## What is true
No consumer's tenant boundary is verified anywhere in the estate. This is
Broken Object Level Authorization, first on the OWASP API Security Top 10
since that list launched.
It is currently **open question 3 in NetKingdom's *Tenancy Posture*, which is a
draft and not a register** — which is precisely why `INTENT.md` names it as the
thing that had nowhere to live. Filing it here does not amend that standard,
does not ratify it, and does not settle the question it poses. A finding may
say a standard is wrong; it cannot change one.
## Why it is a finding and not a research note
The floor asks whether an owner could act and whether recording it changes a
decision. Both are yes, and the second is now demonstrable rather than
asserted: every time a repo has looked at its own boundary this month, it has
found a defect. `RISK-F-0004` (`tenant-engine`, unfiltered event read) and
`RISK-F-0005` (`audit-core`, no tenant filter on read) are two instances found
by two repos in one round.
An absent verification is not the same as an absent boundary. But the sample so
far is two for two, and the register does not get to assume the unexamined
cases are better than the examined ones.
## What is not established
- Whether any consumer boundary *is* in fact correct. Nobody has checked; that
is the finding.
- Who owns the fix. `fix_owner` is `unset` deliberately — see the escalation.
## Register ruling — 2026-08-19
`high` today (`I3` × `L3`), `critical` at production, embargoed, **escalated on
trigger 4 (ownership)**.
Today's impact is `I3` and not `I4` because there is no real tenant data behind
the unverified boundary yet; the consequence of one occurrence is bounded by
what the estate is currently holding. `L3`: no additional step is needed by
anything already inside, and the two confirmed instances say the reach is real
rather than theoretical.
`production_rescore: true`, and this is the finding that matters most on that
day: at production the same defect is `I4` × `L3``critical` — and the
re-score is not optional.
**Escalation, trigger 4.** This is the ownership case the trigger was written
for, in its purest form: the defect is estate-wide, no repo owns "every
consumer's boundary", and a routing exchange cannot settle it because there is
nobody to route it to. Only the operator can say who verifies tenant
boundaries — a repo, a test suite, a review obligation on each consumer — or
that the estate deliberately carries it unverified until production.
Until that is answered, `fix_owner` stays `unset` rather than being assigned to
a repo that has not accepted it. An unowned finding with an honest `unset` is
better than a routed one nobody agreed to.
## Reviews
- **2026-08-19** — filed and graded. Open at review: has an owner been named;
have any further instances been found; is the Tenancy Posture question still
open.