risk-nexus/findings/RISK-F-0003-ops-warden-read-boundary-ungraded-lanes.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

183 lines
8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: RISK-F-0003
type: finding
title: "ops-warden agent read-boundary does not fire on ungraded catalog lanes"
status: open
reported_by: ops-warden
reported_via: ops-warden
routed_by: ops-warden
date_reported: "2026-08-19"
system: ops-warden
environment: production
fix_owner: ops-warden
fix_tracking: WARDEN-WP-0032-T05
# Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-first-grading.md
severity: high
severity_at_production: high
impact: I4
likelihood: L2
fidelity_modifier: false
production_rescore: false
disclosure: embargoed
embargo_condition: "the five exec_capable lanes graded under WARDEN-WP-0032-T05"
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
---
# RISK-F-0003 — the agent read-boundary has a fourteen-lane blind spot
## What is true
`ADR-0004` (ops-warden) states that high-risk lanes refuse raw value streaming
to agent sessions. It is implemented in `src/warden/cli.py:1245`:
```python
if raw_value_stream and entry.is_high_risk and agent_id:
```
and `is_high_risk` is defined in `src/warden/routing/models.py:123` as:
```python
return self.risk == "high"
```
`risk` is an **optional** field on a catalog entry. Of the 27 entries in
`registry/routing/catalog.yaml`, **14 carry no `risk` value at all**. For those,
`is_high_risk` is `False`, so the boundary never fires regardless of what the
lane actually vends.
Five of the fourteen are `exec_capable: true`, meaning `warden access --fetch`
can proxy a real value for them:
| Lane | Owner | Status |
| --- | --- | --- |
| `openbao-api-key` | railiance-platform | active |
| `whynot-design-npm-publish` | railiance-platform | active |
| `key-cape-oidc-login` | key-cape | active |
| `issue-core-ingestion-api-key` | railiance-platform | active |
| `reuse-surface-hub-write-token` | railiance-platform | active |
For these five, an agent session with `WARDEN_AGENT_ID` set can stream a secret
value to stdout, which is the disclosure pattern of 2026-07-16 that WP-0026 and
`ADR-0004` were written to prevent. The control is not bypassed; it is simply
never reached.
## Why it matters beyond these five
The failure mode is **omission, not error**. Adding a lane without a `risk`
value produces a lane outside the boundary, silently, with no warning at load
and nothing in CI that notices. Every future lane inherits this default. The
nine other ungraded lanes are not `exec_capable` today, but `exec_capable` is
itself an editable field.
`ADR-0004` reads as a categorical rule. The implementation is an opt-in list.
## Exposure — stated only as far as ops-warden can support it
- ops-warden is the affected system and owns the catalog, the ADR, and the code.
- `WARDEN_AGENT_ID` is set by agent harnesses; ops-warden has not enumerated
which sessions currently set it, so the population actually exposed is
**not established** and should not be assumed to be zero or large.
- There is a second, independent layer for OpenBao-backed lanes: the OpenBao
policy `agent-high-risk-boundary` denies data-read for agent tokens on the
paths it covers. Whether it covers these five paths **has not been verified
by ops-warden** and should be checked against the live policy rather than
inferred — the paths were graded by the same omission this finding is about.
- No evidence of an actual disclosure through these lanes has been sought or
found. This is a control gap, not a known incident.
## How it was found
Doing `ZONE-WP-0001-T02` (zone-engine) — partitioning the estate for the
security-zone model. Grading every lane on `risk` was a prerequisite for
deriving zone membership, and the count of ungraded lanes is what surfaced it.
## Suggested direction, not a prescription
Two candidate fixes, both ops-warden's to choose between:
1. **Invert the default.** Treat absent `risk` as high, so a new lane is
protected until deliberately graded down. Fails safe; may be noisy.
2. **Make `risk` required**, enforced at catalog load and in CI, so an ungraded
lane cannot be committed. Fails loud; requires grading 14 lanes now.
Either way the grading is real work with real judgement in it, and the five
`exec_capable` lanes are the ones that matter first.
**Update 2026-08-19 — a third direction, and the one being taken.** The operator
has directed that the default derive from **maturity context**: in an early or
experimental context an absent grade is tolerable and explicitly accepted; in a
production context an absent grade resolves to `high`, or `critical` where the
context is critical. This validates against the data here — all five exposed
lanes are owned by production-serving components, so the rule would have caught
every one.
The durable form of that is a zone-model question (`ZONE-WP-0001-T03`), because
the `M0`-`M3` maturity ladder that would drive it has no join to catalog lanes
today. That work is months out, so the two are being run separately: the five
lanes are graded explicitly now under `WARDEN-WP-0032-T05`, and the structural
fix that makes absence impossible follows under `WARDEN-WP-0032-T06`.
Note for whoever sets severity: `.repo-classification.yaml` `category` is **not**
usable as the maturity signal. `railiance-platform`, which runs production
OpenBao and owns three of the five lanes above, is `category: tooling`.
## Related
- ops-warden `ADR-0004` — high-risk lanes refuse raw value streaming
- ops-warden `WP-0026` — disclosure hygiene, safe fetch transports
- `wiki/playbooks/agent-read-boundary.md`
- `RISK-F-0002` — ops-warden sign ungated (same system, different control)
- `zone-engine` `ZONE-WP-0001-T02` — the work that surfaced this
## Register ruling — 2026-08-19
`high` (`I4` × `L2`), embargoed until the five `exec_capable` lanes are graded
under `WARDEN-WP-0032-T05`, no escalation.
**Graded on its worst lane.** Four of the five are `I3`-shaped — a publish
token, an OIDC login, an ingestion key, a hub write token, each bad inside its
own system. `openbao-api-key` is not: it reaches the store the estate's other
secrets live in, and a disclosure there propagates past every boundary the
others respect.
**Likelihood `L2`** — an agent session with `WARDEN_AGENT_ID` is a foothold the
estate does grant. The register holds the line this finding drew: the exposed
population is not established, so it is neither assumed zero nor assumed large,
and the unverified OpenBao `agent-high-risk-boundary` coverage is a review
question rather than an assumption in either direction. Confirming that
coverage for these five paths would lower the grade.
**No fidelity modifier, and it was close.** `ADR-0004` reads categorical while
the implementation is opt-in, so the documentation asserts a boundary that does
not exist for 14 lanes. The modifier is scoped to attestations a system
produces at runtime, and documentation drift is not that. But 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.
**No escalation.** Known, owned, tracked (`WARDEN-WP-0032-T05` for the five
lanes, `WARDEN-WP-0032-T06` for the structural fix), and moving. Severity alone
deliberately does not reach the operator.
**On the maturity-context direction**, which is the operator's and not
re-decided here: the note that `.repo-classification.yaml` `category` cannot
carry the signal is confirmed from this repo's own registration work today.
`railiance-platform` runs production OpenBao and owns three of the five lanes
while classified `tooling`; `risk-nexus` classified itself with the same
vocabulary an hour ago. The maturity ladder needs its own field, and that is
`ZONE-WP-0001-T03`'s to build.
Reasoning: `docs/rulings/2026-08-19-first-grading.md`.
## Reviews
- **2026-08-19** — graded. Next review 2026-09-18 (`high` → 30 days).
Open at review: OpenBao policy coverage of the five paths; whether
`WARDEN-WP-0032-T05` has landed; whether any compliance evidence cites
`ADR-0004` as implemented.