Skip to content

Security & threat model

The claim Calimero makes is narrow and checkable: nobody operating the cluster — Calimero included — can read an app’s data or put new code in front of it without the party the deployment named for that decision. This page lists what that rests on.

Trusted For Checked by
Intel TDX and its attestation (DCAP collateral) That a quote comes from a genuine TD with the measured image, and that a debug TD is not passed off as one Every client and peer, on every new channel
The signed mero-tee release That the measurements in published-mrtds.json are the image Calimero built and signed (Sigstore) Measurements::Release in the client and peer policy
mero-kms Releasing the storage key only to an attested TD The KMS client verifies the KMS against the signed release too, and the node reports the KMS quote it accepted, bound into its own quote (purpose=kms, Attestation), so anyone verifying the node can check which KMS that was
The merod build in that image Everything in this reference Its measurement is part of the image
The person’s authenticator Their passkey WebAuthn, with user verification for step-ups

Not trusted: the host and hypervisor, the disks, the network and any TLS terminator, the operator, other tenants, the app’s publisher beyond its own code, and app code beyond what its owner approved.

Party Can Cannot
Network / proxy See that clients talk to nodes, sizes, timing; drop or delay traffic Read or forge requests, responses or frames; replay a request; impersonate a node without its attested key
Host / hypervisor Stop, freeze, restart a node; read sealed disks; withhold the network Read memory of a non-debug TD; open sealed values without K_c; get K_r (it comes from mero-kms, not the host) or K_c (wrapped under K_r, or delivered by a peer only to the attested TD at a registered node’s address)
Operator (ops token) Register nodes, move replicas onto approved releases, set quotas, take sealed backups, read counts and Raft status, set public release deadlines that stop new work on old images (signed with the operator key); and whatever governance gives it Read state, events, blobs or credentials; sign in as anyone; move an app’s data to an unapproved image (a deadline approves nothing); block an approval; upgrade apps, approve releases or outbound destinations unless governance gives it that decision
A publisher (the organization a package’s signing key is bound to) Where owners decide: approve the releases every instance of its packages runs on (APPROVE_RELEASES holders), and upgrade every instance of a package whose manifest says upgrades: publisher (MANAGE_APPLICATION holders), each with a passkey assertion checked where it applies Read its customers’ apps; take upgrades from instances of an owner package, or turn a package back to publisher once a release declared owner
A node on an approved release Everything this reference describes for the apps whose owners approved its release — (it is the trusted computing base for those apps; that is why every peer is attested)
A node on a release nobody approved (attested, registered: an operator rolled it out) Join the system group, hold and replicate the system state, lead it; propose system commands Receive or read an app’s data, through Raft, internal routes, blobs or presence; act as a user with a session it signed; log a decision (approval, publisher binding, upgrade, transfer, deletion, operator decision) without its maker’s passkey or the operator key
An app’s owner Upgrade it (unless its package says publisher), change its access, approve outbound prefixes for it, approve releases for it while its package’s key is not bound to a publisher (where governance says owner), delete it Read other apps; act for other accounts
A member What the app’s access rule and the app’s own code allow Read another member’s private space; forge a writer rotation, a blob mark or TEE-only state; write if their team row is read-only
An app’s frontend (third-party page) Act as the signed-in person for that package’s apps only; ask the node to show its user a consent page Reach other apps, manage credentials or API keys, approve anything, upgrade or uninstall, or choose what the consent page shows or where it returns
An API key What its scope allows Manage credentials or keys; produce a passkey assertion
  • Reading traffic — the sealed channel, keyed to an attested key, with forward secrecy per session (Networking).
  • A fake or outdated node — the quote check with a measurement policy and a release floor, for clients and peers alike (Attestation).
  • Reading disks — AES-256-GCM under K_c, bound to row, group and column; hidden row keys (Encryption).
  • A new image reaching data — release approvals, enforced by the replicas that hold the data before any Raft entry or snapshot leaves (Deployment governance). Release deadlines are the operator’s, and only availability: they refuse new apps, installs and upgrades for a party on an old image, but approve nothing, so they cannot send data anywhere, and they never refuse an approval.
  • Someone posing as a package’s publisher — a binding carries the package key’s own signature over the cluster, the organization and the key’s binding generation, verified at apply, so it is neither forged nor replayed.
  • New code reaching data — app upgrades held by one named party, with a passkey step-up for owners.
  • Exfiltration over the network — outbound HTTPS only to hosts the operator allows, under prefixes the app’s signed manifest declares and its approver approved, from writing runs only.
  • A stolen session — 15-minute tokens, refresh tokens exchanged once they are an hour old whose reuse after that revokes the session (a copy taken within the hour refreshes beside its owner until then), revocation that holds on every node before the next request and the next refresh.
  • A lagging replica granting stale access — credentials and access judged on fresh system state (a read index).
  • A node on an unapproved release — every internal route judges the identified calling node’s release, a Raft message’s sender must be the node that sent it and a member of the group, sessions are signed by the node that issued them and accepted only from an approved one (Networking, Sessions).
  • Forged authority in the log — decisions carry their maker’s passkey consent or the operator’s signature, checked at apply on every node and used once (system group); other commands are built by nodes from verified credentials, and authority is checked again at apply.
  • A malicious app frontend — its own origin and a package-bound session.
  • An app’s page driving an approval — approvals are refused to package-bound sessions; an app asks the node, whose own consent page shows node-side facts and takes the passkey, and the consent binds the target manifest’s hash or the release’s measurements digest (The consent page).
  • A malicious app — the WASM sandbox and its limits; the host’s key space is closed to it; it reaches only its own blobs and its caller’s private space; xcalls only into entry points within its organization.
  • Proving all this to a user — verify_app_cluster: every replica’s quote, receipt keys, and the governance they all attest; receipts on every answer.
  • The system state on unapproved nodes. Every node of the cluster, whatever its release, holds the whole system state: accounts, passkeys’ public keys, memberships, approvals, refresh-token hashes. Realms per approver are the next phase (docs/specs/gate-system-group.md).

  • Commands without a proof. Commands other than the decisions above (passkeys, API keys, refresh tokens, memberships, invites, node registration, replicas, quotas) still name an actor any node of the cluster can claim.

  • Which node a client talks to. A client checks that a node is attested, not that the user’s approver approved its release, so it sends credentials and passkey assertions to any attested node (F5 in the design).

  • Rollback. A host that restarts a node on an older copy of its disk is not detected. A rollback counter (a mero-kms epoch, restored nodes rejoining as learners) is proposed, not done.

  • Keys per app. One K_c covers every app on a cluster; keys per app from mero-kms are not done.

  • Availability. The host and operator can stop nodes. Raft tolerates the loss of a minority of an app’s replicas, and a session outlives the node that issued it: every node holds every peer’s attested signing key (Failover). A new app’s replicas are spread across the zones the operator registered (placement); moving existing apps between zones is the operator’s (ops placement, ops move).

  • Event audiences. Everyone who reaches an app receives all its events.

  • Side channels on the TD and timing of requests are outside this model.

  • The consent page under TLS. The node’s consent page and its model travel as plain HTTPS, not in the sealed channel: whoever terminates TLS in front of a node can read what a person is asked to approve, or serve another page. It cannot change what is approved nor approve without the passkey (The consent page).

  • A debug image. A debug TD exposes its memory to the host. Clients refuse debug profiles unless told otherwise, and nodes trust debug peers only when they are debug themselves; a cluster on a debug image protects nothing.