Skip to content

concepts

Threat Model — Overview

This page is the short orientation. The depth is in the Security section, which enumerates each default-on control, the secrets-storage contract, and the update trust chain. Read this page first, then follow the cross…

This page is the short orientation. The depth is in the Security section, which enumerates each default-on control, the secrets-storage contract, and the update trust chain. Read this page first, then follow the cross-links.

Adversaries we model

deputyOS images run in a few well-defined places — a Pi on a home LAN, a mini-PC in a closet, a $5 cloud VM behind a single public IP, a desktop launcher on a developer laptop. The threats we design against, and that the default-on controls are sized for, are:

  • Opportunistic LAN-side attackers. Anyone else on the same Wi-Fi or VLAN as the device — a hostile guest, a compromised IoT camera, a laptop on a co-working network. They can probe ports, attempt brute force on SSH, and try to reach the wizard or the PWA.
  • Opportunistic internet-side attackers, when the device is exposed by user choice (a tunnel, a public IP, a Fly.io machine). They cannot reach the device at all by default; if the user has set up a tunnel they can reach exactly the surface the user opened.
  • Supply-chain attacks on upstream agents. A compromised openclaw, hermes, or khoj release would make its way through the release loop unless we catch it. We catch it by pinning upstream tags, by ClamAV / Magika scans during bake, by signing what we ship, and by giving the user a third-party way to verify (make verify VERSION=<v>).
  • Malicious skills and agent-generated code. Hermes can write skills at runtime; agents can be talked into running tools the user did not intend. The defenses are the AppArmor profile, the unprivileged-userns sandbox Hermes uses for command execution, and the cost ledger / quiet hours that bound runaway tool calls.
  • Compromised model-provider credentials. A leaked OpenRouter or Anthropic key is the most common real-world incident. The defenses are mode 0600 on secrets.env, key rotation via deputyctl model set, cost caps that blunt blast radius, and CostAlert hooks that surface unusual spend immediately.

Trust boundaries

The system has a small number of distinct trust layers; understanding where they sit makes the rest of the security documentation easier to read.

LayerWhat it protectsWho enforces it
Signed manifest (cryptographic root)The integrity of every image and the legitimacy of every update.minisign verification in deputyctl update --check and the desktop launcher. Public key baked into every image. See Security → Update trust chain.
Image bake (build-time integrity)What ends up at /opt/deputyos/profiles/<id>/, /var/lib/clamav/, /var/cache/deputyos/.The CI pipeline; reproducibility via make verify VERSION=<v>. SBOM at /etc/deputyos/sbom.json.
AppArmor (process)What each gateway process can read, write, exec, and connect to.The kernel, with profiles at /etc/apparmor.d/deputyos.<id>. See Reference → System → AppArmor profiles.
ufw (network)What inbound traffic the device accepts. Default-deny; allow rules per channel and for the LAN.The kernel netfilter chain. See Security → Default-on controls.
agent user (filesystem)The data partition is owned by agent, not root. The gateway runs as agent.POSIX permissions; systemd User=agent.
secrets.env (mode 0600)Provider keys, tunnel tokens, backup credentials. Readable only by root and (via systemd credential forwarding) the gateway.POSIX permissions, systemd. See Security → Secrets storage.
deputyctl operator surfaceEvery command is non-destructive by default; destructive ones (factory-reset, rollback, update --apply) prompt unless --yes.The CLI itself; documented in Reference → CLI → deputyctl.

Each layer assumes the layers below it are intact. A kernel-level compromise breaks AppArmor and the user-id boundary; a manifest-signing-key compromise breaks every layer below it.

What’s not in scope

Documenting limits explicitly is part of the awareness-of-limitations principle. The following are not threats deputyOS attempts to defend against, and the user should know that:

  • Physical attacks. A person with the device in their hands can swap the SD card or NVMe, attach a JTAG, or read the data partition. deputyOS does not enable full-disk encryption by default; opt-in encryption is a deferred milestone.
  • Kernel zero-days. AppArmor is a confinement, not a hypervisor. A kernel bug that lets a process escape AppArmor breaks our process boundary. We patch via image revs as upstream patches land.
  • Side-channel attacks on shared cloud hosts. A neighbour on a shared Hetzner or Vultr host running Spectre-class attacks is out of scope; the cloud provider owns that boundary.
  • Compromise of the user’s model-provider account by other means. If your OpenRouter account is breached upstream, your key on the device is irrelevant.
  • Covert tracking by the user’s ISP. DNS, NTP, and provider HTTPS traffic are visible to the network. deputyOS does not route through Tor or a VPN by default.
  • Targeted nation-state adversaries. This system is sized for the threats a self-hosting hobbyist faces, not for high-stakes high-resource attackers.

Layered defenses summary

The full enumeration is in Security → Default-on controls; the table below is the orientation map.

LayerWhat it protectsHow to verify
Signed manifestEvery download and updatedeputyctl version shows the manifest signature and the public key fingerprint; deputyctl update --check re-verifies on every update. See Security → Update trust chain.
Reproducible bakeWhat’s actually in the imagemake verify VERSION=<v> rebuilds the image and asserts the SHA256 matches. SBOM at /etc/deputyos/sbom.json.
AppArmor enforceProcess-level confinementaa-status shows every profile in enforce mode. Doctor verifies on boot. See Reference → System → AppArmor profiles.
ufw default-denyInbound network surfaceufw status verbose lists the deny-by-default chain and per-channel allows.
fail2banBrute-force resistance on SSH and the wizardfail2ban-client status shows the active jails.
Hardened sysctlsKernel attack surface/etc/sysctl.d/90-deputyos.conf is the source of truth. Doctor verifies the values are applied.
ClamAV + MagikaInbound file scanningclamdscan --version (or clamscan on RAM-constrained targets); Magika is invoked by the gateway pre-write.
agent userFilesystem isolationid agent, ps -u agent. The gateway is never run as root.
secrets.env mode 0600Provider key isolationstat -c '%a %U' /etc/deputyos/secrets.env returns 600 root.
Key-only SSHRemote-access posturesshd -T | grep -E '^(passwordauthentication|permitrootlogin)'.
ZRAM + cgroup limits + systemd-oomdGraceful pressure responseswapon, oomctl status, journal entries. See Operations → Monitoring and logs.
Cost guardrailsBounded financial blast radiusdeputyctl cost shows the ledger; CostAlert hooks fire on threshold breaches. See Operations → Cost guardrails.

Where to go next

Search

Search index isn't built yet. Run npm run build to generate it (Pagefind writes to dist/pagefind/).