Skip to content

Security model

CAESAR controls a real home. The security posture is conservative on purpose — and concrete: this page describes what's actually wired, not aspirations. The security-review track (the SR-NNN items referenced below) is the operative record of what's been hardened and what's still open.

Trust boundaries

   HTTP clients              External LLM APIs
   (phone, browser,          (data egress hazard;
    n8n, webhook senders)     keys held only by Praetor)
            │                          │
            │  bearer (SR-001)         │  HTTPS to provider
            ▼                          ▼
   ┌────────────────────────────────────────────────┐
   │                  Praetor                       │
   │  trusted; the only component that holds        │
   │  long-lived secrets (LLM keys, HA token,       │
   │  dashboard token, NKEY seed)                   │
   └─────┬──────────────────┬──────────────┬────────┘
         │                  │              │
         │ REST + WS        │ NATS         │ HTTPS
         │ (HA token)       │ (optional)   │
         ▼                  ▼              ▼
   Home Assistant      Legion pool      ntfy.sh
                       (in-process +
                        plugins +
                        remote workers
                        with per-NKEY auth)

Authentication, per surface

Surface Default Hardening
/v1/chat, /v1/devices Loopback bind, open to localhost CAESAR_SERVER__API_TOKEN ⇒ bearer-token required (SR-001 fu). Startup logs a warning if you bind non-loopback without a token.
/v1/hook/{trigger_id} — Per-trigger bearer token (ADR-0032); 64 KiB body cap; rate-limited cooldown.
/dashboard/* Returns 404 until token is set CAESAR_DASHBOARD__TOKEN enables it; signed session cookie; per-cookie revocable records (SR-007 fu); optional separate signing key (SR-006).
/metrics Open; loopback-bound by default CAESAR_METRICS__TOKEN ⇒ bearer-token required (SR-003).
NATS bus (Legion) Disabled When enabled, opt into per-identity NKEY auth via CAESAR_BUS__AUTH__ENABLED (ADR-0027). Per-worker subject scopes documented in RUN-A-WORKER.
HA Bridge Disabled until URL + token are set Long-lived HA token, treated as a high-value secret.

Principles

  1. One credential vault. Only Praetor holds long-lived secrets (HA token, LLM provider keys, dashboard token, NKEY seed). Workers run in-process under Praetor (sharing its credentials) or on other hosts with their own NKEY seed (which authenticates them on the bus but doesn't grant access to LLM or HA credentials).
  2. Side effects are mediated. Every HA service call and every Legion tool call passes through the Policy Engine (ADR-0013 + ADR-0028). Plugin tools ride the same allowed_tools allow-list as in-tree tools — no plugin can call anything an operator hasn't explicitly permitted.
  3. Declarative policy. Operators describe what's allowed in policy.yaml; the engine evaluates per call. New rules don't require a code release.
  4. Decisions are auditable. Every brain decision lands in audit_log with the inputs that produced it. Plugin loads, tool calls, policy denials, trigger fires — all recorded with stable event-type codes for grepping. See ADR-0012.
  5. pip install is the trust act for plugins. Plugins (ADR-0035) run same-process with Praetor. CAESAR doesn't sandbox them — installing a plugin is the same trust act as adding a Python dependency. Operators paranoid about the surface can pin to an explicit allow-list via CAESAR_PLUGINS__ALLOWLIST.

Threat model

Threat Mitigation
Network-adjacent attacker hits /v1/chat Loopback default; CAESAR_SERVER__API_TOKEN required for LAN exposure (SR-001 fu).
Webhook URL leaks Per-trigger bearer (Authorization: Bearer …) constant-time-compared; 64 KiB body cap; cooldowns coalesce repeats.
Dashboard cookie is exfiltrated 7-day TTL by default; revocable per-cookie session records (SR-007 fu); signing key can be rotated independently of the auth token (SR-006).
LLM is prompt-injected via a tool output Tool outputs are passed as ToolResult blocks, not free-text injected into system prompts; policy gates every subsequent action.
HA token is exfiltrated by a worker Workers (in-process and remote) never see the HA token. All HA traffic goes through Praetor's bridge.
LLM API key is exfiltrated by a worker Same. Workers never see provider keys; they go through the LLMGateway Praetor owns.
Malicious plugin is installed via pip Trust posture matches the rest of pip install: review the package first, pin versions, verify Sigstore attestation when published with Trusted Publishers (SR-011 fu). CAESAR_PLUGINS__ALLOWLIST pins the surface. The Policy Engine still gates every tool call regardless of plugin claim.
Compromised remote worker host Per-identity NKEY auth (ADR-0027) — workers can only publish/subscribe to their declared subject scopes. A stolen seed lets an attacker impersonate one worker, not the whole pool.
LAN-adjacent attacker scrapes /metrics Loopback by default; CAESAR_METRICS__TOKEN for LAN exposure (SR-003).
Supply-chain compromise of a transitive dependency Pinned versions; dependency-review CI job; Dependabot PRs with the auto-merge gate held for security alerts.
Pathological audit-log payload bloats the table Per-string clamp at write time (CAESAR_MEMORY__AUDIT_MAX_STRING_CHARS, default 16 KiB; SR-008).
Audit log eventually fills the disk TTL retention sweeper (ADR-0020) deletes rows older than CAESAR_MEMORY__RETENTION_DAYS.
Operator's policy is misconfigured YAML parsed at startup, not first-call; bad rules fail loud. Audit log surfaces every policy decision for review.

Out of scope

  • An attacker with root on the host running Praetor. Self-hosted homelab software cannot help here. CAESAR-side hardening guidance (loopback bind, secret-manager-over-.env, regular backup) is in CONFIGURATION.md and OPERATIONS.md.
  • Defending against a malicious operator. CAESAR trusts its owner.
  • Sandboxing plugins. Subprocess- and container-isolated plugin models were considered and rejected for v2.0 — see ADR-0035 §Alternatives. Operators who want isolation should run CAESAR itself in a container with whatever filesystem and network restrictions match their threat model.

Reporting issues

See SECURITY.md — use GitHub's private vulnerability reporting, not public issues.

Track record

SECURITY-REVIEW.md lists every SR-NNN finding from the v1.0 security review (ADR-0025), its status, and the PR that closed it. New findings get tracked the same way.