Security and Trust Model
The design goal is that compromising the control plane is not the same as compromising a host. Below: who holds which key, what each can and cannot do, what a host checks, and which attacks are tested — including the ones that are not yet.
In Decentralized.Host a host pins the cluster root key and checks every assignment against 18 ordered checks before running it, so a control plane holding a valid member key still cannot make a host run work its policy refuses. Fuzzing and an external security review have not been done yet.
Keys
| Key | Held by | Can | Cannot |
|---|---|---|---|
| Cluster root | operator, offline | sign rosters, delegate to members, create invites, sign root rotations, grant federation, attest artifacts | run anything on a host whose policy refuses it |
| Member key | each control-plane member | sign bundles and assignments within its root delegation | enlarge the roster, change host policy, roll a host back, issue work for a revoked host |
| Host key | each host | sign enrollment, observations, wg-binding, storage evidence, its own ledger | speak for another host; its signed seq cannot be replayed |
| Session capability | operator browser or CLI | act as api.read / api.write / api.admin until it expires | exceed the caveats of any block in its chain |
What a host checks before it runs anything
- The bundle chains to the pinned root — the root from its join token, or from a rotation that root signed.
- The bundle signer is in the root-signed roster, and its state index is not older than one already accepted.
- The assignment is signed by a roster member, names this host, and has a generation at least as high as any already admitted.
- The capability chain authorizes this assignment, host, generation, artifact digest and resources, down from the root.
- Its own
policy.yaml: tiers, runtimes, digest pinning, publisher attestation, federated work, caps. - The artifact bytes hash to the assigned digest.
If any check fails, nothing new starts; if the same generation is already running it is held, not stopped. Every decision goes into the host's own hash-chained ledger. In total the host evaluates 18 ordered checks (spec §9.3), shown per replica by dh describe app.
Failure and attack cases
| Case | Outcome | Tested by |
|---|---|---|
| Control plane down or partitioned | offline-hold: admitted work continues, new work refused, observations queued | chaos cp-total-outage, network-partition; M1 |
| Compromised member (valid member key) | can only sign within its delegation; every host still applies its own policy; rollbacks and impostor keys refused | pkg/node/sovereignty_test.go |
| Replayed, forged or tampered observation | rejected with a specific reason; state unchanged | chaos replay-forgery; M1 |
| Stolen host key | `dh node revoke-key` revokes that key | M3 |
| Revoked host | cut from mesh and routing, replicas rescheduled, new admission blocked | chaos revoked-host; M3 |
| Host clock skew | CLOCK_SKEW detected from bundle timestamps; admitted work held | chaos clock-skew |
| Host ledger tampering | LEDGER_CORRUPT; no appends to the broken chain; operator seal recovers with the break recorded | chaos journal-corruption |
| Audit ledger truncation or rewrite | detected offline by hash chain and signed checkpoints | pkg/audit; M1 |
| Storage corruption | BLAKE3 verification on read; quarantine; repair from peers with evidence | M2; chaos storage-replica-loss, disk-full |
| Network observer | TLS on member APIs from first start, pinned bootstrap, mutual-TLS Raft, WireGuard between hosts | tls_test.go; M7 |
Security tests
Deliberate limits
- › The root key is the single anchor. Rotation is supported, but a stolen root can sign a rotation — keep it offline.
- › A member with a valid delegation can sign harmful-but-permitted work (for example, scaling an app to zero). Host policy bounds what runs; it cannot judge intent. Use `dh freeze` if you suspect compromise.
- › The process runtime does not enforce CPU or memory limits; admission details say so. Use the docker runtime for enforcement.
- › Session capabilities are bearer tokens. They stay in sessionStorage and the URL fragment, never server logs, and expire.
- › Root key custody (offline signer or HSM) is not implemented.
Full model: docs/trust-model.md. To report a suspected vulnerability, contact the maintainer privately through github.com/CodesbyFebin rather than opening a public issue.