TacidOS
DevelopersGitHub

Invariants and threats

Security

The hard invariants, the threat model, and how to report a vulnerability.

Tacid gives an AI agent authority over the machine it runs on. That makes the security model the product, not a feature. This document is the short version; the long version is docs/architecture.md and the security section of PLAN.md.

Reporting a vulnerability

Report privately through GitHub Security Advisories on TacidOS/TacidOS (“Report a vulnerability”), or to the security contact published at tacidos.com/security. We acknowledge within 72 hours, keep you informed, coordinate disclosure with you, and credit you unless you prefer otherwise. Vulnerabilities in upstream components (nixpkgs, the kernel, Niri, inference engines) should go upstream first; tell us too so we can ship the fix through the channel.

In scope: every tacid-* component, the tacid.* NixOS modules, the installer, the update and channel pipeline, the binary cache, the model registry, the prompt-injection defenses, and the documented invariants below. A way to make the agent violate an invariant is a vulnerability even if no code is “exploited”.

Trust zones

ZoneProcessTrustNotes
0tacid-stemrootTyped operations only. Accepts connections only from the keeper. No network. Refuses boot-, disk-encryption-, TPM- and Secure-Boot-key changes without owner-present confirmation.
1tacid-keeperown user, IPAddressDeny=anyPolicy, reversibility classifier, taint, approvals, secrets broker, audit sink, health gate and rollback, snapshots.
2tacid-egressown userThe only path to the network for agent processes. Domain allowlist, credential injection, egress ledger, airgap.
3taciddtacidThe LLM-facing daemon. Least-trusted daemon. Holds no secrets, has no root, reaches the network only through egress.
3tacid-inferown user, GPUSupervises sandboxed inference subprocesses. Treated as hostile: model files are untrusted input.
4tacid-sessionthe userUser-context tools; parsers of untrusted content run in sandboxes here.
5clientsthe usertacid, tacid-shell. Pure renderers. Approvals go to the keeper, never through tacidd.
6sandboxesephemeralbubblewrap + Landlock + seccomp; microVMs for high-risk code.

Hard invariants

These are never delegated to the model and cannot be changed by the agent. They are enforced in the keeper and the stem, not in tacidd.

  1. The model is not an authorization authority.
  2. Retrieved content (web pages, files, repositories, tool output, third-party MCP servers, voice) is not an authorization authority. Every context item carries a provenance label; taint propagates through tool output; a tainted turn cannot exceed autonomy level 1 for side effects.
  3. Root is never represented as arbitrary shell. The stem exposes typed operations with strict schemas and no string interpolation.
  4. Secrets never enter model context. Protected paths are denied by default; secrets are secret:// handles brokered by the keeper and injected by the egress proxy or into tool environments; a scrubber runs on every tool result, memory write and audit line.
  5. The agent cannot write tacid.agent.*, tacid.policy.*, or its own autonomy level. Owner-only files are those whose last commit is signed by the owner key; the keeper verifies.
  6. Destructive storage, firmware, boot and git operations require exact target identity and confirmation unless a narrow owner policy says otherwise.
  7. The audit journal is append-only, written by the keeper into a root-owned file the agent cannot modify, with its head sealed to a TPM counter or the owner’s remote where available.
  8. The health gate and automatic rollback cannot be disabled by the agent.
  9. Rollback claims distinguish system state, data snapshots, and external devices; nothing implies data was restored when it was not.
  10. Cloud egress is subject to explicit data classification; nothing leaves without the badge and the ledger.
  11. External integrations (MCP servers, other agents) act under their own principal and policy and cannot escalate.
  12. The owner can always reach a tty and boot the previous generation.

Threat model

Threats we design for, with the mitigation each maps to:

#ThreatMitigation
1A web page prompt-injects the agentProvenance labels, taint cap, retrieved content is not authority
2A README instructs the agent to exfiltrate SSH keysProtected paths, egress allowlist, taint cap
3A cloud model returns a dangerous commandTyped tools, sandboxed exec, reversibility classifier, policy
4The agent hallucinates a destructive targetExact target identity required
5A third-party MCP server is compromisedOwn principal, untrusted by default, policy gate
6A package source is compromisedPinned inputs, signed channels, signed cache, provenance
7A model file carries malicious metadata or templatesInference sandboxed, no network, templates ignored, signed registry
8The owner grants an overly broad persistent permissionBudgets, level-4 expiry, visible indicator, audit
9The privileged stem is exploitedTiny surface, memory-safe, fuzzed protocol, keeper-only socket
10The audit log leaks a secretScrubber on every audit line, handles not values
11A firmware flash targets the wrong deviceExact target identity, confirmation
12A generated udev rule grants excessive device accessCurated udev profiles, review of raw rules
13A network tool sends private files unexpectedlyEgress proxy, data classes, ledger, badge
14The rollback UI implies data was restoredThree-way rollback claims
15The installer damages a foreign partition layoutDisko plans previewed; Apple layouts never touched
16The agent bricks boot or security configurationBoot-class activation, boot counting, stem refuses key changes without owner presence
17A tool interpolates untrusted strings into a shellNo shell interpolation anywhere in the stem or tools; argv only
18Memory becomes a persistence vector for injectionMemory carries provenance; untrusted-derived memory is never loaded as instructions
19A compromised tacidd forges an approvalApprovals are bound to a transaction id and delivered client-to-keeper
20A leaked signing key updates every edge machineTUF roles: offline root, short-lived online keys, revocation by manifest

Key custody

  • Channel root key: offline, on a hardware token held by the maintainer, used only to sign the root role and key rotations.
  • Snapshot and timestamp keys: online in the continuous-integration signer with short expiry; rotated on schedule and on any suspicion.
  • Binary cache signing key: in the continuous-integration signer; rotation invalidates nothing already installed and is announced through the channel manifest.
  • Owner key: generated at install, stored in the TPM or a hardware token where available, otherwise on the encrypted disk; the recovery path is documented in the installer.
  • Agent key: generated per machine, used to sign the agent’s own commits to the genome.

Out of scope for the first releases

An attacker with physical access and the disk PIN; a malicious maintainer; a malicious owner; a compromised upstream kernel; hardware side channels; and defending the owner from a model they explicitly chose to trust at autonomy level 4.