# Evolution 7 — Threat model

Scope: the path `CAIN-42 JIT decision -> signed envelope -> TALOS verify kernel -> confined worker -> ledger`,
as implemented in `cain/talos`. Assets: the host and gateway process, files outside an authorised scope,
network reachability, signing keys, the replay ledger, the truthfulness of published evidence.

## Adversaries

| Id | Adversary | In scope | Notes |
|---|---|---|---|
| A1 | Malicious or prompt-injected agent that controls proposals, parameters, tool output and retrieved text | yes | cannot sign; can call any adapter with any arguments |
| A2 | Caller of the TALOS adapters inside the gateway that passes wrong identity, wrong request, a forged or replayed envelope | yes | |
| A3 | Hostile code running as the authorised workload inside the worker | yes | arbitrary native code, forks, signals, sockets |
| A4 | Holder of a valid but stale, revoked, cross-tenant or other-audience envelope | yes | |
| A5 | Concurrent verifiers, crashes, ledger loss or replacement | yes | |
| A6 | Party who tampers with evidence or presents old or partial evidence as current | yes | bundle verifier |
| A7 | Thief of a CAIN signing key or approver key | detection and recovery only | can mint valid envelopes until revoked |
| A8 | Root on the host, a kernel exploit, the hypervisor or cloud provider | **out of scope** | software controls here do not survive this |
| A9 | Someone who restores an older copy of the ledger file | partly | needs the operator's floor-raise procedure |
| A10 | Network attacker between CAIN and TALOS | yes for integrity (signature), n/a for confidentiality (not provided) |

## Threats and controls

| Threat | Adversary | Control | Evidence | Residual |
|---|---|---|---|---|
| Forged or altered envelope | A1 A2 A10 | Ed25519 over a domain-separated canonical form covering every field; trust roots held by TALOS; issuer bound to key | E7-A-001..006, E7-P-002, F7-01 | key theft (A7) |
| Parser differential, type confusion, oversize | A1 A2 | strict parser: duplicate keys, floats, unknown or missing fields, wrong types and >16 KiB rejected | E7-A-010..016 | — |
| Run something other than what was authorised (TOCTOU, argument, cwd, env, target, path substitution) | A1 A2 | request digest signed and recomputed at execution; scope containment checked by TALOS | E7-E-010..016, E7-E-041..043, F7-07 | executable resolved via fixed PATH at exec, not hashed |
| Cross-tenant, cross-agent, cross-session, cross-audience reuse | A2 A4 | each bound and compared | E7-A-020..024, E7-E-022, F7-05 | the caller supplies the expected identity; TALOS cannot know the caller authenticated it correctly |
| Replay, retry, concurrent use | A4 A5 | one atomic consumption per envelope in a durable ledger | E7-L-001..003, E7-A-060, F7-10, F7-19 | single host only |
| Stale policy, expired, future-dated, over-long envelope; no clock; clock rollback | A4 | pinned policy version and digest; bounded lifetime and skew; fail closed without a clock; ledger time high-water mark | E7-A-030..044, F7-03, F7-17 | rollback detection needs the ledger intact |
| Revoked key or decision; emergency | A7 | ledger revocation re-checked inside the consumption transaction; invalidation floor | E7-A-050..052, E7-L-004..006, F7-04, F7-21 | revocation after start does not stop a running worker |
| Self-asserted human approval | A1 | approver signature over the exact operation, verified by TALOS | E7-A-070..072, E7-E-024, F7-09 | approver key custody and what the human is shown |
| Prompt injection changes scope, tenant, policy or key | A1 | untrusted data only changes digests | E7-A-093 | the policy itself may be too permissive |
| Verifier, ledger or sandbox failure becomes execution | A5 | every exception and every unknown result is a non-ALLOW verdict; request withheld until controls are measured | E7-E-030..039, F7-11, F7-14 | — |
| Workload reads or writes outside scope; symlink and traversal | A3 | Landlock; worker-side `O_NOFOLLOW` for governed file actions; canonical paths only | E7-W-001..006 | host files are visible to `stat()` in allowed parents; no mount namespace |
| Workload reaches the network, DNS or local sockets | A3 | empty network namespace; seccomp `socket()` filter; Landlock TCP port rules when network is allowed | E7-W-010..014 | with network allowed: UDP and non-TCP protocols to any address are **not** restricted |
| Workload regains privilege or attacks host processes | A3 | all capabilities dropped; no_new_privs; seccomp denylist; PID namespace | E7-W-020..022 | denylist, not allowlist; kernel bugs |
| Workload outlives the call, floods output or exhausts resources | A3 | in-namespace supervisor; PID-namespace teardown; output cap; rlimits | E7-W-040..047 | no cgroup: total memory and (for uid 0) process count are bounded only by the wall clock |
| Secrets leak into the worker | A3 | empty launcher environment, fixed base environment, closed descriptors, request on a pipe | E7-W-030..032 | secrets the scope itself makes readable |
| Evidence tampering, stale or contradictory status, secrets in the kit | A6 | standalone verifier with distinct exit codes; unsigned is reported as NOT_RUN | E7-V-001..016 | no trusted signature on this bundle |
| Ungoverned paths | A1 | **none**: outside the boundary | `enforcement_inventory.json` | see ENFORCEMENT_COVERAGE.md |
