127.0.0.1:4766) by default.
The canonical, version-controlled threat model is
THREAT_MODEL.md in the repository root — this page mirrors it. Vulnerability reporting and the disclosure SLA live in SECURITY.md.Trust boundaries
What Comis defends against
What Comis does not defend against
- A compromised host or malicious operator — the operator holds the master key, config, and DB.
- Full kernel sandboxing on non-Linux hosts —
bwrapis Linux-only; macOS uses best-effortsandbox-exec; Docker-Desktop/Windows run the exec/terminal tools unsandboxed. - The
exectool on a host with no sandbox provider — it currently fails open. - A fully adversarial model provider beyond what injection-wrapping and the output guard catch.
- Brokering OAuth / subscription-token CLIs — only header/query API-key and bearer injection is brokered today.
- Resource exhaustion / DoS from the operator’s own agents, across a daemon restart (default config) — the bounded-autonomy guards (spawn ceiling, per-root budget, call-rate limit, outward quota) are real hard bounds within a daemon run, and with durability off (the default) their state is in-memory: the counters/meters reset on restart, so they bound a single live run, not cumulative spend across restarts. Opting into
autonomy.durability.enabledcloses the most dangerous half of this — the run’s checkpoint + consumed budget + outward-send ledger are persisted, so a restart resumes the run (re-seeding budget from the record) and never re-sends a message (the exactly-once outward ledger). The transient rate-limit and quota windows still reset on restart even with durability on (only run state and outward sends are durable); cumulative cross-restart rate limiting remains future work. - Confidentiality of data the operator deliberately routes to third-party providers or chat platforms.
- Physical access, side channels, and compromise of Node.js or the OS itself.
Agent action classification
Every agent-driven action is classified byActionClassifier. Unknown actions default to destructive (fail-closed), and the registry is locked after bootstrap so a malicious plugin cannot downgrade a classification at runtime.
Confirmation gating is covered in Approvals; classified actions are recorded per Audit Logging.
Defense in depth
See Defense in Depth, Skill Sandboxing, Exec Sandbox, and the Credential Broker.
Known limitations
Severity is the impact if the precondition is met.
Self-reported benchmark figures (memory accuracy, cache savings) are self-authored, small-N, and LLM-judged — directional, not independent guarantees.
Per-channel coverage of the exactly-once outward guarantee is uneven — by design, not a gap. The restart-resend defense reconciles a crashed-mid-send by asking the channel “did this actually send?”. Discord, Slack, and Matrix can be queried (recent history + bot-author + content-digest match), so a crashed-mid-send there resolves automatically to sent (acknowledge once) or not-sent (replay once) — and, critically, only when the scan actually covers the send window: a truncated or paged-past history read stays
unresolved rather than risking a false not-sent. iMessage, IRC, and Email cannot be queried for their sent history — so a crashed-mid-send on those resolves to unresolved, which Comis handles by parking the send and escalating to the operator, never by guessing. That is the safe, surfaced outcome on both sides: never a silent double-send, and never a silent drop. The guarantee is therefore full and automatic on queryable channels and parked-and-surfaced on the ones that cannot answer — the honest representation of where the exactly-once guarantee is complete versus operator-decided.No-downgrade posture model. The invariant is enforced over the four config-derived confinement dimensions — exec, filesystem, network, uid. For the sub-agent spawn path today the exec sandbox dimension is the active one (exec
always is more confined than exec never); filesystem/network/uid are present in the comparator but inert until the deferred terminal path lands. The design’s “broker-only parent → open child” phrasing refers to a runtime sandbox network mode, not an operator config field (no broker-only/open config key exists); in operator config the same escalation is expressed as a more-confined parent (e.g. exec always) spawning a less-confined child (exec never), which is what comparePosture refuses.Reporting a vulnerability
Do not open public issues for vulnerabilities. Use the private reporting channel and follow the coordinated-disclosure process documented inSECURITY.md.