risk-nexus/docs/method/severity.md
tegwick f0db7c83ca RISK-WP-0002: findings publish whole; method docs public except escalation
Operator ruled both. Findings publish as the file a reader gets —
including RISK-F-0001's record that this register graded it critical
while its fix notice sat unread. A summary would be a second document per
finding kept in sync by hand, and drift is the failure this repo most
distrusts; and a published register containing only other repos' defects
reads as an accusation, while one containing its own reads as a record.

Method docs public except escalation, which is restricted because it
names spend thresholds and describes when the operator personally is
interrupted — a map of where attention is scarce, needed by nobody
judging a finding.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:43:48 +02:00

8.4 KiB

id type title status owner adopted workplan review_interval disclosure revision last_reviewed
RISK-METHOD-SEVERITY method Severity: how bad, how likely, and what is not a risk at all adopted risk-nexus 2026-08-19 RISK-WP-0001-T01 6m public adopted-1 2026-08-20

Severity

This is risk-nexus's judgement instrument. It is not canon, it is not a standard, and it binds nobody else. It exists so that two findings graded a month apart are graded the same way, and so that a grade can be argued with.

It was written against three real findings (RISK-F-0001, RISK-F-0002, RISK-F-0003) and it must keep grading those three sensibly or it is wrong.

The two axes

Impact — what happens if it goes wrong once

Band Name Test
I1 negligible Confined to one component. No data leaves it, no record is falsified, no recovery is lost.
I2 limited One system's data or availability. Recoverable. Confined to a single tenant, actor or lane.
I3 serious Crosses a boundary — tenant, system, or trust — or removes recoverability for one system.
I4 severe Crosses the estate. What is compromised here propagates to everything that trusts it, or the data loss is unbounded.

Impact is scored at one occurrence, not at the worst imaginable campaign. "An attacker who already owns the cluster could do this too" is not an impact argument.

Likelihood — how far anyone has to reach

Band Name Test
L1 remote Requires access nobody currently holds and no ordinary process grants.
L2 possible Requires a foothold the estate does grant somewhere — an in-cluster workload, an agent session, a scoped token.
L3 likely Reachable from inside the normal working set with no additional step.
L4 present No barrier at all, or it is already happening.

Likelihood is about reach, not about intent or about whether anyone has bothered. risk-nexus does not model attackers; it models what the system permits.

Where the reporter has not established exposure, the finding says so and the grade uses the band the stated facts support — not the worst case, and not zero. RISK-F-0001 explicitly declines to assume a default-deny NetworkPolicy exists; the grade must decline with it, and the unverified fact becomes a review item rather than a silent assumption in either direction.

The grid

L1 L2 L3 L4
I4 medium high critical critical
I3 low medium high critical
I2 low low medium high
I1 note low low medium

Four severities: low, medium, high, critical. note is not a severity; see the floor.

The fidelity modifier

A control that lies is one impact band worse than the same control absent.

Apply +1 impact band (capped at I4) when the failure mode produces a false record rather than no record: an attestation that a check passed when nothing checked, an audit line asserting an authorization that was never made, a green signal derived from an unreachable test.

The reasoning is RISK-F-0002's and the register adopts it: an absent control is a gap you can find by looking; a lying control is a gap that survives looking, because the evidence you would look at is the thing that is wrong. Only one of the two states misleads the person investigating afterwards.

The modifier applies to the state being scored. A finding that describes both states — control absent today, control lying if switched on in the wrong order — gets two scores and one of them is the register's headline; see "Which state is scored".

Which state is scored

The headline severity is the state of the world today. A hazard that would be created by a future action is not the headline, because a register that scores hypotheticals stops describing the estate.

The hazard is not lost. It is recorded on the finding as a named constraint with its own grade, and it attaches to whatever action would trigger it — usually another finding's remediation. RISK-F-0002 is the worked example: the gate being off is today (headline), the gate being switched on while the oracle is forgeable is a constraint on RISK-F-0001's fix, graded separately and higher.

If the constraint's grade is higher than the headline, the finding says so in its ruling. A reader must not be able to come away with the low number and miss the high one.

Build mode

Every finding is graded twice:

  • severity — today, in build mode, with today's likelihood.
  • severity_at_production — the same impact, with likelihood re-read for a system carrying real users and real tenant data.

Build mode legitimately lowers both axes, for different reasons: likelihood, where the reach itself depends on a production deployment that has not happened; and impact, where the data that would be exposed does not exist yet. What it must never lower is severity_at_production — the defect does not improve because the calendar has not reached it.

Amended 2026-08-19 (RISK-WP-0001-T07). This paragraph originally said build mode was a likelihood input and never an impact one. Grading the unverified tenant boundary broke that: what build mode changes there is the consequence of an occurrence, not the reach of it. The instrument was wrong on first hard use and is corrected rather than worked around.

Where the two grades differ, the production transition is a mandatory re-score. docs/method/review.md binds the review date to it, so the re-score is a scheduled event and not somebody's memory.

Non-adversarial findings

Likelihood is written as reach because most findings are about someone getting somewhere. Where a finding is about loss, corruption or outage — no backup, no recovery path, an eviction-prone deployment — there is no attacker to model.

For those, likelihood reads as the chance of the triggering event inside one review interval: L1 would be surprising, L2 is an ordinary failure the estate has seen before, L3 is expected in the normal course of running, L4 is already happening. Impact is unchanged: what is lost, and whether it comes back.

Added 2026-08-19 (RISK-WP-0001-T07). Forced by RISK-F-0006, where the defect is an absent backup and the reach reading produced nonsense.

The floor

INTENT.md: if a finding would not change anyone's decision, it is a note, not a risk. Concretely, a register entry requires both:

  1. An owner who could act. Some repo, or the operator, can do something about it. No actor, no entry.
  2. A decision that changes. Recording it alters what someone does, when they do it, or what they must not do first.

Fails either test → it is a note in notes/, not a finding in findings/. Notes are not graded, not reviewed, and not published. They exist so that "we saw it" survives without inflating the register.

An I1/L1 cell is note in the grid for the same reason: something that is both negligible and unreachable is a thing we know, not a risk we carry.

Two things the floor does not exclude:

  • Known and deliberate. RISK-F-0002 is a decision somebody made on purpose. It still passes the floor, because it changes what may be switched on and in what order. Deliberate is not the same as tracked.
  • Omission-shaped. RISK-F-0003 is a default that silently produces ungoverned lanes. The individual lane is small; the default is not.

Provenance is a grading input

All four defects known to this register were found by repos reading their own code against a ladder, within days of each other. None was found by monitoring.

Where a finding's provenance is "we happened to look", the register does not get to assume that similar defects would have been caught. That raises likelihood for the class, not for the instance, and it belongs in the ruling's reasoning rather than in a modifier — the register grades what is filed, and notes when the filing was luck.

Recording a grade

The finding's front-matter carries:

severity: critical              # headline, today
severity_at_production: critical
impact: I4                      # band, before modifiers
likelihood: L3
fidelity_modifier: false        # true if +1 applied, with the reason in the ruling

and the ruling section states impact, likelihood, any modifier, and the one sentence that would have to become false for the grade to change.