dashboard: remove the state-file endpoint, the file_refs path scan and the unused marked and dompurify deps
This commit is contained in:
parent
0f7b403803
commit
6d080ea28b
11 changed files with 12 additions and 419 deletions
|
|
@ -339,8 +339,7 @@ Under `/var/lib/hyperhive/agents/<name>/`:
|
|||
`work/` doesn't walk up into `state/AGENTS.md` and load the agent's
|
||||
own identity. Survives `destroy`/recreate, gone on `--purge`. Counted
|
||||
in the per-agent disk metric (`measure_agent_disk`) together with
|
||||
`state/` and the container rootfs. The dashboard doesn't serve it:
|
||||
the state-file endpoint reads `state/` only.
|
||||
`state/` and the container rootfs. The dashboard doesn't serve it.
|
||||
|
||||
### Cross-agent access to state
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
## Agent trust model
|
||||
|
||||
The sections below document specific mechanisms (the state-file endpoint,
|
||||
nixbld isolation, privilege separation). This section frames the model they
|
||||
The sections below document specific mechanisms (nixbld isolation,
|
||||
privilege separation). This section frames the model they
|
||||
serve: **what hyperhive defends, what it deliberately doesn't, and where the
|
||||
operator is accepting risk.** It's the reference for "is it safe to give an
|
||||
agent capability X?."
|
||||
|
|
@ -20,9 +20,8 @@ default**. Isolating credentials _from the agent itself_ is therefore **not a
|
|||
goal**: an agent can read its own tokens, its own `/home/<name>/.claude`, and
|
||||
run arbitrary commands as root inside its container. (The narrow exception is
|
||||
_cross-tenant_ leakage — for example the unsandboxed-nix-build `0600` token policy
|
||||
below stops a build's nixbld user reading the agent's own forge token, and the
|
||||
state-file endpoint stops one agent proxying another's files. Those harden the
|
||||
boundary; they don't sandbox the agent from itself.)
|
||||
below stops a build's nixbld user reading the agent's own forge token. That hardens
|
||||
the boundary; it doesn't sandbox the agent from itself.)
|
||||
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
|
|
@ -162,45 +161,10 @@ into an agent's config, that agent has exactly that reach, with no hyperhive
|
|||
layer narrowing it. Scope external tokens tightly at the source (the external
|
||||
provider) before handing them over.
|
||||
|
||||
## State-file endpoint security model
|
||||
## Agent-supplied names in paths
|
||||
|
||||
`GET /api/state-file?path=<p>` serves files from agent state dirs and
|
||||
the shared space to authenticated dashboard users (browser, operator).
|
||||
It accepts two allow-listed root prefixes and rejects all other paths
|
||||
before touching the filesystem:
|
||||
|
||||
- `/var/lib/hyperhive/agents/<n>/state/` — per-agent durable notes
|
||||
(canonical host form or the in-container view `/agents/<n>/state/`)
|
||||
- `/var/lib/hyperhive/shared/` — shared docs (`/shared/` in-container)
|
||||
|
||||
`/state/...` without an agent prefix is explicitly _not_ accepted — it's
|
||||
ambiguous from the host's perspective.
|
||||
|
||||
Defense-in-depth layers (in order):
|
||||
|
||||
1. **Allow-list prefix check** — rejects without touching the filesystem
|
||||
if the path doesn't match either root.
|
||||
2. **No symlinks below the matched root** — each path component is
|
||||
checked with `symlink_metadata` before canonicalize. A sub-agent
|
||||
that plants `ln -s /other/secret /agents/me/state/peek` can't proxy
|
||||
another agent's file through this endpoint (canonicalize would
|
||||
happily resolve the symlink to a still-within-allow-list path).
|
||||
3. **Canonicalize as belt-and-braces** — resolves `..`/`.` traversal
|
||||
and rejects if the result escapes the roots.
|
||||
4. **`state/` subdir constraint** — under `AGENTS_ROOT`, the second
|
||||
path component must be `state/`. Applied, proposed git repos and
|
||||
config dirs are off-limits.
|
||||
5. **World-readable check** — file must have `mode & 0o004` set.
|
||||
A `0600` file inside `state/` would otherwise be accessible to any
|
||||
operator with dashboard access.
|
||||
|
||||
`scan_validated_paths` (broker-message ingest, linkifier) uses the same
|
||||
`resolve_state_path` helper so security rules stay in sync — the
|
||||
dashboard renders anchors only for tokens that passed the same checks the
|
||||
read endpoint enforces.
|
||||
|
||||
The same invariant holds wherever an agent-supplied name reaches a filesystem
|
||||
path: the agent socket's `GetAgentMeta` takes `name` as a serde-validated
|
||||
Wherever an agent-supplied name reaches a filesystem path, hyperhive validates
|
||||
it first. The agent socket's `GetAgentMeta` takes `name` as a serde-validated
|
||||
`hive_types::Ident` (or falls back to `Ident::parse` for the "self" case)
|
||||
before building `agent_notes_dir(name)`, so a `..` component can't traverse.
|
||||
|
||||
|
|
|
|||
|
|
@ -555,23 +555,6 @@ below — some endpoints aren't in it yet.
|
|||
stdout+stderr as `text/plain`. Used by the `↓ raw` / `↓ download
|
||||
raw` links in the build tabs. Works on both finished and in-progress
|
||||
build logs.
|
||||
- `GET /static/marked.js` serves the vendored `marked` bundle used
|
||||
for markdown previews.
|
||||
- `GET /api/state-file?path=<host-or-container-path>` — bounded
|
||||
text read of a file under the per-agent `state/` subtree or
|
||||
the shared `/var/lib/hyperhive/shared/`. Accepts the
|
||||
container-view forms (`/agents/<n>/state/...`, `/shared/...`)
|
||||
and the host form. Canonicalises + verifies the path stays
|
||||
inside the allow-list, refuses anything but a regular file,
|
||||
refuses `/agents/<n>/claude` / `config` subtrees, truncates
|
||||
bodies at 1 MiB. No dashboard page calls it since the flow page
|
||||
stopped existing.
|
||||
|
||||
The broker forwarder still detects path tokens **server-side at
|
||||
broker-message ingest**: it calls `scan_validated_paths(body)` —
|
||||
same allow-list helper the read endpoint uses — and attaches
|
||||
the verified file tokens to the event as `file_refs: Vec<String>`.
|
||||
No dashboard page reads that list either.
|
||||
- `GET /api/reminders` — list pending reminders for the
|
||||
dashboard's queued-reminders panel.
|
||||
- `GET /api/stats-hive?window=<1h|4h|24h|3d|7d|30d|all>` — hive-wide
|
||||
|
|
|
|||
Loading…
Reference in a new issue