Skip to Content
Kai

Security

How Kai keeps workspaces apart, protects secrets and talks to the network.

Workspaces are separate

Every row in Kai's database belongs to a workspace, and Postgres row-level security enforces it. The server connects as a role that can't bypass those policies and sets the workspace and user on each transaction, so a bug in a query can't read another workspace's data. A test suite runs every policy against a real Postgres.

Conversations are private to their owner, even within a workspace.

Secrets

API keys, extra headers, MCP header and environment values, OAuth tokens and OAuth client secrets are encrypted with AES-256-GCM under KAI_ENCRYPTION_KEY, with a fresh nonce each time. Each ciphertext is bound to its row and purpose, so a ciphertext copied elsewhere can't be decrypted.

Secrets are never returned by the API or written to logs. The UI shows whether a key is set and its last four characters. Error messages from providers have the key and header values removed before they're stored.

Passwords are hashed by the authentication library, and email codes are stored hashed.

Outbound requests

Everything Kai fetches on someone's behalf (model APIs, MCP servers, OpenAPI documents and calls, OAuth endpoints) goes through one fetch that:

  • refuses private, loopback, link-local and metadata addresses unless the key or server has Allow private network (which the instance must allow with KAI_ALLOW_PRIVATE_NETWORK);
  • checks the address after DNS resolution and connects to that address, so a second DNS answer can't redirect it;
  • follows redirects only within the same origin, re-checking each hop;
  • caps response sizes and times out.

The browser

Kai sends a strict content security policy: scripts only from Kai itself (and one inline script, by hash), images only from Kai, object storage and the library, no framing. Responses also send nosniff, no-referrer and DENY for framing.

Model output is rendered as Markdown, and tool arguments and results are shown as text.

Tools

  • Each tool call can require approval, and the workspace decides which.
  • Approvals remembered by people are tied to the tool's definition; if a server changes a tool, Kai asks again.
  • A server's own instructions are only added to the system prompt when an admin turns that on, after reading them.
  • stdio servers run commands on the Kai host without a sandbox. They're off unless KAI_ALLOW_STDIO_MCP=true; only allow them where you trust every workspace admin.

Limits

Kai limits how many replies a person can run at once (4) and how often they can call expensive endpoints (testing keys and servers, fetching documents), and caps request bodies at 2 MB.

On this page