RISK-F-0003 — ops-warden agent read-boundary blind spot on ungraded lanes
ADR-0004 reads as a categorical rule; the implementation is an opt-in list. is_high_risk is risk == "high", and risk is optional — 14 of 27 catalog lanes carry no value, so the boundary never fires for them. Five are exec_capable, so warden access --fetch can stream a real value to an agent session. Reported by ops-warden about ops-warden, found while partitioning the estate for zone-engine's ZONE-WP-0001-T02. Severity, disclosure and escalation left unset — those are risk-nexus's to set. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
15b003471e
commit
f5147c2987
1 changed files with 106 additions and 0 deletions
106
findings/RISK-F-0003-ops-warden-read-boundary-ungraded-lanes.md
Normal file
106
findings/RISK-F-0003-ops-warden-read-boundary-ungraded-lanes.md
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
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: unset
|
||||
# risk-nexus's fields, deliberately left unset by the reporter.
|
||||
severity: unset
|
||||
disclosure: unset
|
||||
escalation: unset
|
||||
---
|
||||
|
||||
# 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.
|
||||
|
||||
## 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue