Compare commits
No commits in common. "38e083ed3de28ae6139aaa83b500e86df7f3e758" and "d8b18f29721cabc60954aa835aa8ef0f43d6dd0f" have entirely different histories.
38e083ed3d
...
d8b18f2972
3 changed files with 1 additions and 240 deletions
125
INTENT.md
125
INTENT.md
|
|
@ -1,125 +0,0 @@
|
||||||
# INTENT — risk-nexus
|
|
||||||
|
|
||||||
## Why this repo exists
|
|
||||||
|
|
||||||
`risk-nexus` is where the estate holds what it knows is wrong, what might be
|
|
||||||
wrong, and what the outside world requires of it — with a severity, an owner,
|
|
||||||
and a date. It serves `risk.coulomb.social`.
|
|
||||||
|
|
||||||
**Owned by `the-custodian`**, alongside `policy-nexus`. One of its duties is
|
|
||||||
deciding what must reach the operator personally rather than sitting in a
|
|
||||||
register.
|
|
||||||
|
|
||||||
Before this repo existed, three things had nowhere to live.
|
|
||||||
|
|
||||||
**Findings landed in whichever document was open.** The estate's largest known
|
|
||||||
gap — that no consumer's tenant boundary is verified anywhere, which is
|
|
||||||
Broken Object Level Authorization, top of the OWASP API Security Top 10 since
|
|
||||||
that list launched — is currently open question 3 in an unratified draft
|
|
||||||
standard. It was found by research, it has no owner, no severity, and no date.
|
|
||||||
A finding recorded in the document that happened to discover it is a finding
|
|
||||||
that disappears when that document is superseded.
|
|
||||||
|
|
||||||
**Disclosure had no mechanism.** In build mode the estate publishes everything,
|
|
||||||
which is right: there are no users to expose. That stops being right at
|
|
||||||
production, when the same architecture disclosure a consumer must read becomes
|
|
||||||
a map for an attacker. There is currently no way to hold a finding while it is
|
|
||||||
fixed and publish it once it is — only publish-now or forget.
|
|
||||||
|
|
||||||
**Regulation was consulted and discarded.** Whether key destruction satisfies
|
|
||||||
an erasure obligation, whether the estate is an in-scope entity under a given
|
|
||||||
regime, what a procurement rule requires — each was researched at the moment
|
|
||||||
someone needed it and never retained. The same question gets asked twice and
|
|
||||||
the answer silently expires.
|
|
||||||
|
|
||||||
## What it owns
|
|
||||||
|
|
||||||
- **Finding intake.** Security, architecture, operational and compliance
|
|
||||||
findings, from any source: research, review, incident, external report.
|
|
||||||
- **Severity and triage.** What this actually risks, how likely, how bad.
|
|
||||||
- **Remediation tracking** — not remediation. Who owns the fix, what state it
|
|
||||||
is in, and whether it has stalled.
|
|
||||||
- **Disclosure timing.** Whether a finding is publishable now, embargoed until
|
|
||||||
fixed, or permanently restricted; and the record that a delay was deliberate
|
|
||||||
rather than a document quietly going missing.
|
|
||||||
- **Regulatory intake**, scoped to regulation bearing on the estate — rules
|
|
||||||
constraining data it holds, markets it sells into, or obligations it has
|
|
||||||
taken on. Moved here from `policy-nexus`, because deciding what a rule
|
|
||||||
demands of us is a judgement about risk, not an act of publishing.
|
|
||||||
- **The escalation rule.** What must be discussed with the operator personally
|
|
||||||
rather than recorded and routed. This is the duty `the-custodian` carries as
|
|
||||||
owner, and the rule itself must be written down rather than exercised by
|
|
||||||
instinct.
|
|
||||||
|
|
||||||
## What it does not own
|
|
||||||
|
|
||||||
- **Fixing anything.** A finding is routed to the repo that owns the defect,
|
|
||||||
which fixes it under its own workplan. A risk service that fixes things
|
|
||||||
becomes a second engineering team with no boundary.
|
|
||||||
- **Publication.** `policy-nexus` is the publication surface. This repo decides
|
|
||||||
*whether and when* something is published; it does not host it.
|
|
||||||
- **Blocking delivery.** In build mode a finding is information, not a gate.
|
|
||||||
If that changes it will be a deliberate decision recorded here, not a habit
|
|
||||||
that accretes.
|
|
||||||
- **Legal advice.** A regulatory record states what a source said and when.
|
|
||||||
What the estate must therefore do is the owning repo's decision.
|
|
||||||
- **Deciding what canon says.** Canon is `the-custodian`'s and NetKingdom's. A
|
|
||||||
finding may say a standard is wrong; it cannot amend one.
|
|
||||||
|
|
||||||
## The failure this repo must avoid
|
|
||||||
|
|
||||||
A risk register nobody reads is worse than no register, because it converts
|
|
||||||
"we did not know" into "we knew and did nothing" while changing no behaviour.
|
|
||||||
Two consequences for design:
|
|
||||||
|
|
||||||
- **Findings must expire or escalate.** A finding that has sat untouched past
|
|
||||||
its review date is itself a finding. Silence is not resolution.
|
|
||||||
- **The register must be small enough to read.** Recording everything makes
|
|
||||||
nothing legible. If a finding would not change anyone's decision, it is a
|
|
||||||
note, not a risk.
|
|
||||||
|
|
||||||
## The escalation duty
|
|
||||||
|
|
||||||
Most findings should be routed and tracked without the operator's attention.
|
|
||||||
Some must not be. Deciding which is the substance of the oversight `the-
|
|
||||||
custodian` holds here, and getting it wrong in either direction is a failure:
|
|
||||||
escalating everything makes the operator the queue, escalating nothing makes
|
|
||||||
the register a place where serious things go quiet.
|
|
||||||
|
|
||||||
The rule is not yet written. Candidate triggers, to be settled rather than
|
|
||||||
assumed: anything exposing real tenant data; anything creating a legal or
|
|
||||||
regulatory obligation; anything requiring spend; anything where two repos
|
|
||||||
disagree about who owns the fix; and any finding whose remediation has stalled
|
|
||||||
past a stated interval.
|
|
||||||
|
|
||||||
## Relationship to the rest of the estate
|
|
||||||
|
|
||||||
`risk-nexus` reads from everywhere, decides severity and timing, and routes
|
|
||||||
work to the repo that owns it. It publishes through `policy-nexus` and never
|
|
||||||
directly. Like that repo, it is downstream by construction and must not become
|
|
||||||
a second source of truth — a finding is a claim about a system, and the system
|
|
||||||
remains authoritative about itself.
|
|
||||||
|
|
||||||
The register is no longer empty. `RISK-F-0001` arrived on 2026-08-17: a live
|
|
||||||
authorization bypass in `flex-auth`, self-reported during a framework review.
|
|
||||||
Three more defects surfaced in the same round and are recorded inside it as
|
|
||||||
visible-but-unfiled, pending this repo setting the precedent for what warrants
|
|
||||||
a record of its own.
|
|
||||||
|
|
||||||
**The first finding already tested the deferral.** Controlled disclosure is
|
|
||||||
recorded above as deferred to production, on the reasoning that build mode has
|
|
||||||
no users to expose. `RISK-F-0001` is a live authorization bypass in the service
|
|
||||||
every other service trusts, and today the choice is publish or hold with
|
|
||||||
nothing in between. That may still be the right deferral — but it is now a
|
|
||||||
decision taken with a real case in hand rather than a hypothetical one.
|
|
||||||
|
|
||||||
Also waiting: the unverified tenant boundary, the absent noisy-neighbour
|
|
||||||
characterisation, and the erasure-versus-audit tension — open questions in
|
|
||||||
NetKingdom's *Tenancy Posture*, which is a draft and not a register.
|
|
||||||
|
|
||||||
## What good looks like
|
|
||||||
|
|
||||||
Nobody is surprised. A gap that was known is recorded with a severity and an
|
|
||||||
owner, a regulation that applies was found before it was needed, a fix that
|
|
||||||
stalled was visible while it stalled, and the things that genuinely needed the
|
|
||||||
operator's judgement reached them without the things that did not.
|
|
||||||
13
README.md
13
README.md
|
|
@ -1,14 +1,3 @@
|
||||||
# risk-nexus
|
# risk-nexus
|
||||||
|
|
||||||
Risk register and regulatory intake for the estate. Serves
|
A risk management service.
|
||||||
`risk.coulomb.social`. Owned by `the-custodian`.
|
|
||||||
|
|
||||||
Holds findings — security, architecture, operational, compliance — with a
|
|
||||||
severity, an owner and a date; decides whether and when each is published; and
|
|
||||||
decides which must reach the operator personally rather than sitting in a
|
|
||||||
register.
|
|
||||||
|
|
||||||
It does not fix things: findings route to the repo that owns the defect. It
|
|
||||||
does not host: `policy-nexus` is the publication surface.
|
|
||||||
|
|
||||||
- Intent: `INTENT.md`
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
---
|
|
||||||
id: RISK-F-0001
|
|
||||||
type: finding
|
|
||||||
title: "flex-auth /v1/check authenticates no caller"
|
|
||||||
status: open
|
|
||||||
reported_by: flex-auth
|
|
||||||
reported_via: rapp-postgres
|
|
||||||
routed_by: rapp-postgres
|
|
||||||
date_reported: "2026-08-17"
|
|
||||||
system: flex-auth
|
|
||||||
environment: production
|
|
||||||
fix_owner: flex-auth
|
|
||||||
fix_tracking: FLEX-WP-0015-T02
|
|
||||||
# The three fields below are risk-nexus's, not the reporter's. Left unset
|
|
||||||
# deliberately: the reporter says what is true, this repo says how bad it is
|
|
||||||
# and who hears about it (INTENT, "What it does not own").
|
|
||||||
severity: unset
|
|
||||||
disclosure: unset
|
|
||||||
escalation: unset
|
|
||||||
---
|
|
||||||
|
|
||||||
# RISK-F-0001 — flex-auth authenticates no caller on the decision surface
|
|
||||||
|
|
||||||
## What is true
|
|
||||||
|
|
||||||
`POST /v1/check` and `POST /v1/batch_check` authenticate no caller. Any
|
|
||||||
workload with network reach to the ClusterIP Service can assert any subject and
|
|
||||||
any tenant and receive an authoritative **allow**.
|
|
||||||
|
|
||||||
`flex-auth` is the estate's authorization oracle. Every service that delegates
|
|
||||||
a decision to it is relying on an answer that anyone able to reach the pod can
|
|
||||||
obtain for any identity they care to name.
|
|
||||||
|
|
||||||
Self-reported by `flex-auth` as `A0` on their own inbound surface, in their
|
|
||||||
Tenancy Posture review. Their words: "flex-auth is the estate's authorization
|
|
||||||
oracle and it trusts its callers completely."
|
|
||||||
|
|
||||||
## How it was found
|
|
||||||
|
|
||||||
Not by a probe, an incident, or an alert. By `flex-auth` assessing themselves
|
|
||||||
against the Tenancy Posture A ladder during a review they were asked to do —
|
|
||||||
and their own note says they did not know they were carrying it.
|
|
||||||
|
|
||||||
That provenance matters for triage: nothing was watching for this, and nothing
|
|
||||||
would have found it. It has presumably been true for as long as the endpoint
|
|
||||||
has existed.
|
|
||||||
|
|
||||||
## Exposure, as far as the reporter stated it
|
|
||||||
|
|
||||||
- The Service is `ClusterIP`, so reach requires a workload inside the cluster.
|
|
||||||
- No claim was made that network policy restricts which workloads can reach it,
|
|
||||||
and this record does not assume one. **If a default-deny NetworkPolicy fronts
|
|
||||||
the service, that materially changes the exposure and should be verified
|
|
||||||
rather than inferred** — `flex-auth` did not state it either way, and I have
|
|
||||||
not checked, because doing so would be reporting on a system I do not own.
|
|
||||||
|
|
||||||
## What makes it worse than a single service's defect
|
|
||||||
|
|
||||||
A false allow from this endpoint is not confined to `flex-auth`. It is the
|
|
||||||
answer other services act on. `tenant-engine` separately reports that its own
|
|
||||||
mutations are authorized by `flex-auth` and that direct authority over its rows
|
|
||||||
would mean "privilege escalation across NetKingdom rather than data tampering
|
|
||||||
confined to one store". The same reasoning applies to a forged allow.
|
|
||||||
|
|
||||||
## Owner and state
|
|
||||||
|
|
||||||
`flex-auth` owns the fix and has tracked it as `FLEX-WP-0015-T02`, to ship
|
|
||||||
through the staged-promotion path rather than a direct apply. They classify it
|
|
||||||
as the only urgent item of their five follow-ups. Nothing is asked of them by
|
|
||||||
this record beyond what they have already committed to.
|
|
||||||
|
|
||||||
## What this repo is asked to decide
|
|
||||||
|
|
||||||
1. **Severity.** Not the reporter's to set.
|
|
||||||
2. **Disclosure.** Build mode is currently public-by-default, and this is
|
|
||||||
precisely the class of finding where that stops being obviously right — a
|
|
||||||
live authorization bypass in the service every other service trusts. The
|
|
||||||
controlled-disclosure scheme this repo anticipates does not exist yet, so
|
|
||||||
the choice today is publish or hold, with no mechanism between them.
|
|
||||||
3. **Escalation.** Whether this reaches the operator personally. The candidate
|
|
||||||
triggers in INTENT include "anything exposing real tenant data" — this
|
|
||||||
exposes the decision that governs access to it, which may or may not be the
|
|
||||||
same thing, and that judgement is this repo's.
|
|
||||||
|
|
||||||
## Related, reported at the same time and not yet filed
|
|
||||||
|
|
||||||
Three further defects surfaced from the same review round. They are recorded
|
|
||||||
here so they are visible, not filed as findings, because filing them was not
|
|
||||||
asked for:
|
|
||||||
|
|
||||||
- `tenant-engine` — `events()` returns the entire event log unfiltered. A live
|
|
||||||
cross-tenant read at `E2`.
|
|
||||||
- `audit-core` — read path applies no tenant filter; a credential with
|
|
||||||
`may_read` can read any tenant's events. Bounded by deployment (`may_read:
|
|
||||||
false` on the production sender) and not by code. Tracked `AUDIT-WP-0008-T04`.
|
|
||||||
- `apps-pg` (`railiance-platform`) — no backup configured at all: no
|
|
||||||
`barmanObjectStore`, no retention policy, `BestEffort` QoS. `R0` there means
|
|
||||||
no recovery, not merely no erasure policy.
|
|
||||||
|
|
||||||
All four were found the same way, by repos reading their own code against a
|
|
||||||
ladder, within a day of each other. That is a fact about the estate's
|
|
||||||
observability worth carrying into triage: **four live defects, none found by
|
|
||||||
monitoring.**
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue