Threat Model¶
!!! warning “Mermaid diagrams require JavaScript”
Diagrams on this page use Mermaid rendered via
sphinxcontrib-mermaid. They require JavaScript to be enabled and, in
non-air-gapped environments, an outbound connection to cdn.jsdelivr.net
(pinned to mermaid.js 10.2.0 via mermaid_version in docs/conf.py).
In air-gapped deployments, host mermaid.min.js locally and update
mermaid_version in docs/conf.py to point to the local path.
Note: This page documents currently implemented and tested threat boundaries. It is intentionally scoped to evidence available in repository code/tests and generated outputs.
Trust Boundary¶
The runtime is the sole policy authority. Adapters are untrusted callers:
Adapters submit tool-call intents via POST /v1/tool. The runtime evaluates the
active policy bundle and either:
Allows — executes the tool and returns
{decision:"allow", output:...}Denies — returns HTTP 403 with
{decision:"deny", reason:...}
No adapter code path can flip Deny to Allow. This invariant is tested in
runtime/interceptor_test.go:TestInterceptorDenyCannotBeOverridden.
Trust Boundary Diagram¶
Fail-Closed Design¶
The runtime is designed to fail closed under every degraded condition:
Condition |
Behaviour |
|---|---|
Policy evaluator returns error |
Default: Deny |
No active policy bundle loaded |
|
Corrupt or incompatible bundle |
Fall back to LKG bundle; if no LKG, deny-all |
OCI cosign verification fails |
Release rejected; no activation; lifecycle event emitted |
Control-plane unreachable |
Local cache serves decisions; no degradation to allow-all |
Tests: TestInterceptorDenyCannotBeOverridden, TestInterceptorFailClosed in runtime/.
Protected Assets¶
Asset |
Description |
Protection |
|---|---|---|
A-01 |
Local segment store integrity |
Disk ceiling (INV-04) + |
A-02 |
Policy bundle authenticity |
Cosign signature (Step 1) + bundle hash |
A-03 |
Agent artifact identity |
OCI digest match (Step 2) + behavioral fingerprint (Step 3) |
A-04 |
Decision authority |
Runtime fail-closed; deny-all fallback; adapters cannot override |
A-05 |
Peer identity |
mTLS required for all segment exchange (INV-09) |
Hash Algorithm Assignments¶
Two hash algorithms are used with distinct, non-interchangeable roles:
Field / purpose |
Algorithm |
Prefix |
Source |
|---|---|---|---|
|
BLAKE3 |
|
|
|
SHA-256 |
|
OCI registry manifest |
|
SHA-256 |
|
OCI registry manifest |
|
SHA-256 or BLAKE3 |
caller-specified |
Caller-supplied |
Policy |
SHA-256 |
|
|
!!! danger “Never substitute BLAKE3 for SHA-256 or vice versa”
behavioral_fingerprint is always BLAKE3. OCI digests are always SHA-256.
Mixing them produces a fingerprint mismatch at Step 3 of the verification pipeline.
See Contracts for the full hash-role reference table.
Adversary Capabilities¶
Current documented non-goals:
Non-Goal |
Rationale |
|---|---|
Byzantine consensus defence |
No consensus protocol exists (INV-02) |
RF jamming defence |
Physical layer outside scope |
Infinite resource saturation |
Bounded by INV-04/INV-07/INV-13; not a security guarantee |
Beacon-based peer authorisation |
Beacon is unauthenticated by design; see Beacon Privacy |
Security Invariant Mapping¶
Threat |
Mitigating Invariant(s) |
Enforcement |
|---|---|---|
Shared-storage compromise |
INV-01 (No Shared State) |
Startup path check + |
Distributed coordination attack |
INV-02, INV-03 |
|
Disk exhaustion DoS |
INV-04 (Disk Ceiling) |
|
Unauthenticated peer exchange |
INV-09 (Authorization Boundary) |
mTLS + CRL; FI-C3-02 |
Mission-layer privilege escalation |
INV-10 (Decoupling) |
|
Retry amplification attack |
INV-12 (Bounded Retry) |
Monotonic counter; FI-C4-01 |
Per-peer bandwidth exhaustion |
INV-13 (Bounded Quota) |
Token bucket; FI-C3-03 |
Security Acceptance Criteria¶
From Workplan v0.6 §9.2 (tracked here for Phase 3 completion):
Trust boundaries documented: control-plane vs runtime-plane vs adapters vs peer nodes
Key material handling: cosign keys, mTLS certs — storage and rotation documented
Beacon non-auth stance:
beacon-privacy.mdexplains discovery vs authorisation separationFail-closed verified:
TestInterceptorDenyCannotBeOverridden,TestInterceptorFailClosedAll 4 cosign verification steps documented with tamper-test cross-references
Evidence¶
runtime/interceptor.go,runtime/interceptor_test.goruntime/server.go,runtime/poller.gopolicy/manager.go,policy/evaluator.gooci/sign/verify.go,oci/sign/verify_tamper_test.goedge/transport/tcptls.go,edge/transport/transport_test.goedge/quota/localquota.go,edge/retry/retry.godocs/_generated/test-outputs/demo-output.txt
Do Not Do¶
❌ Do NOT trust adapter-supplied identity or role claims — policy is enforced by the runtime
❌ Do NOT allow segment exchange before mTLS handshake completes (INV-09)
❌ Do NOT use beacon data for peer authorisation — beacon is unauthenticated (see Beacon Privacy)
❌ Do NOT use BLAKE3 for OCI digests or SHA-256 for
behavioral_fingerprint— they are not interchangeable
See Also¶
Source:
docs/security-model.md(legacy; to be superseded by this page)Source:
docs/contracts.md(legacy hash reference)