Known limits
Every limit of what Straza protects in one table, with what it means for you, what reduces it today and what the roadmap plans, and the scale ceilings of one deployment.
On this page
Straza leaves some risks with you, and this page names each one. A security reviewer or an auditor reads the table as the list of residual risks to accept, reduce or track. Each row gives the limit and the mechanism behind it, what it means for your deployment, what reduces it today, and what is planned. The link in each row leads to the page that explains the mechanism in full. The Planned column quotes only what the roadmap states, and a row the roadmap does not name says so.
| Limit | What it means for you | What reduces it today | Planned |
|---|---|---|---|
| A user-mode hook is advisory. The hook runs as the user, and an agent that can run anything on its machine can run around it. | A local tool rule on such a machine stops a mistake or a naive prompt injection. It does not hold against an agent that sets out to bypass it. | A managed install in root-owned paths, with the managed level required for sensitive roles through governance.minAttestation or a policy require block. The sandbox image for processes without a hook. |
Not on the roadmap. |
| An MCP server added outside the gateway. A server a person registers in their own harness never reaches the gateway, and only the advisory hook sees its calls. | Its credential sits on that machine, and governing it is that person’s responsibility. | Register every MCP server that holds a credential in Straza, so the gateway decides its calls and keeps the credential. On Claude Code, a managed install writes an exclusive managed MCP file, so the harness loads only the servers named there. | Not on the roadmap. |
| The attestation level comes from the client. The server compares the hashes a check-in reports with its registry, and it cannot tell which program sent them. | A process that runs as the person can check in with the registered hashes and get a managed session, because the device credential stays in the person’s home directory. |
Treat managed as a guard against changed enforcement files. Never make it the only control in front of an action that must not happen. |
A device-bound client certificate to complement attestation. |
| A sandbox session cannot prove its image. A check-in reports whether the install is managed, its platform and its hashes, and nothing about the image it ran in. | That a session ran inside the sandbox image is your deployment’s claim. | Keep high-blast-radius permissions on roles that require managed, and put MCP tools behind the gateway. |
Attestation of the image a session ran in, in the scale-out tier. |
| The sandbox image leaves two paths open. Every binary on its allowlist runs without a decision, and the shipped compose file leaves the container’s network routable. | A per-argument rule holds at the boundary only for a tool that is absent from the image. | Keep the allowlist as shipped, put tools whose arguments matter behind the gateway, and set internal: true on the sandbox network with only strazad attached. |
Not on the roadmap. |
| Interpreter indirection. An agent can write a script and then run it, and the hook sees only the interpreter call. | A rule that matches a command’s text does not see what the script does. | A rule can deny the tagged interpreter call or send it to the heuristic classifier. The audit sentinel, once governance.sentinel.enabled is true, records a written file that is then run, after the fact. |
Not on the roadmap. |
| What Straza does not try to do. Root on an endpoint owns every process on it, the hook included. Computation inside a process is ungoverned, and model traffic is never proxied. | No enforcement on a machine holds against its own administrator. Straza sees no prompt or completion unless a policy turns on conversation recording at the hook. | Keep credentials behind the gateway, where they never reach the machine, and govern the actions that leave the process. | None, by design. |
Client files are plain text. The device credential, the session token and an AI agent’s key sit under ~/.straza as JSON or YAML with mode 0600, never encrypted or kept in a keychain. On Windows the files inherit the access list of the profile folder. |
Every process of the person can read them, an agent included, and so can anyone with the disk or a backup of it. | Disk encryption and separate operating system accounts. Revoke the device when a machine or its backup is lost. | Not on the roadmap. |
| The device credential is a bearer secret. Nothing in a check-in is signed by a key the machine holds, and a renewal leaves the old credential valid until its own expiry. | A copy of the credential starts new sessions as its user until you revoke the device or disable the user. | strazactl devices revoke or disabling the user, both checked before any mint. A device credential lasts 30 days from its issue or its last renewal. |
Not on the roadmap. |
| A copied session token can be refreshed. A session token lives 300 seconds, and its holder can refresh it like the original while the session and the user stay active. | A copied token keeps working until you revoke the session, until it goes 600 seconds without a refresh, or until governance.sessionMaxLifetime ends the session, 12 hours by default. |
strazactl sessions revoke, disabling the user, or a shorter session lifetime. |
Not on the roadmap. |
| A hook learns of a revocation late without the daemon. The client daemon receives a revocation as a pushed event. Without it, a hook keeps allowing from its cache until its token expires. | A revoked session can keep running local tools for up to 300 seconds after its token was minted. A standalone hook that cannot reach strazad adds its offline grace of 900 seconds. The gateway refuses a revoked token at once. | Run straza daemon on every workstation, and keep governance.offlineGraceTTL at 0, the enterprise default. |
Not on the roadmap. |
Snapshot keys are trusted on first use. straza enroll pins the snapshot signing keys the server publishes, over whatever connection it runs on. |
An enrollment over a connection someone else controls can pin their key, and the machine then accepts their policy. | Enroll over TLS or on a network you trust. | Not on the roadmap. |
Sign-in routes carry one rate limit. server.loginPerIPRPS, 2 requests a second per client address, covers the password submit and, in enterprise, the agent token endpoint. /v1/enroll and /v1/checkin carry none, and no account locks after failed attempts. |
An online guesser is slowed by bcrypt and that limit alone. Behind a proxy every client shares the proxy’s address and its budget. | Rate-limit the sign-in routes at your ingress, and alert on the login failures that the audit chain records. | Not on the roadmap. |
| Standalone signs in with passwords. The built-in issuer checks a password hashed with bcrypt and asks for no second factor. | A standalone account is as strong as its password. | The enterprise profile, where your identity provider owns the login and its second factor. | Passkeys for the standalone issuer. |
First-boot passwords land in the server log. The first boot writes the bootstrap admin password, in standalone, and the break-glass password, in both profiles, as the password field of a warning line. |
Every copy of that log, in a log shipper or a kept container log, holds full administration until the password changes. | Change both passwords after the first boot with strazactl users set-password, and keep the first boot’s log out of shared log stores. |
Not on the roadmap. |
An agent can enroll an approval device as its person. strazactl keeps its login in ~/.straza/credentials.json, where every process of the person can read it, and the server stores what an enrolling device reports without checking it. |
A device an agent enrolled decides every request its person may decide, the agent’s own included. A signed decision proves which device decided, never that a person acted. | Do admin work where no agent runs as you, or run strazactl logout when you finish. Review strazactl approvers list and revoke a device nobody recognizes. Keep approval.unsignedOwnDecisions at false. |
A confirmation on a separate device before a new approval device can decide. |
| A new approver certificate strands enrolled phones. A phone trusts the approver listener by the key it pinned at enrollment. | Losing or rotating the approver TLS pair makes every phone enroll again. | Back up the pair with the store, and compare the pin that /version reports after every move or restore. |
A rotated approver certificate that announces its successor over the authenticated channel. |
A database copy holds both signing seeds. The session and snapshot signing keys sit unencrypted in the signing_keys table, and the server publishes every snapshot key it stores, retired ones included. |
A copy mints any token for any user and signs a policy that every enrolled workstation accepts. No rotation withdraws an old snapshot key. | Protect the database and its backups as you would the keys. After a suspected copy, run strazactl signing-keys rotate session and revoke the device and approver credentials the old key signed, because it verifies them for 30 more days. |
Not on the roadmap. |
| Manifest values are stored in plain text. A server’s manifest is plain JSON in the database. Lists and exports mask secret-shaped values, and storage stays plain. | A credential typed into a manifest’s environment, arguments or address leaks with any copy of the database. A reader without apps:write can test a guessed value at a masked place through a drafts check. |
Keep every secret in the server’s secret, which strazactl apps secret set seals at rest. |
Not on the roadmap. |
| A Rego module can run past its time limit. The 100 ms limit is checked between evaluation steps, so one allowed built-in over a very large value runs to its end. The hook reads what the harness sends with no size cap. | A module can hold a large call for seconds and use memory in proportion before the decision denies. | Review a Rego module as code, and give the right to write policy only to people you would trust with code. | Not on the roadmap. |
A remote server may sit at an internal address. strazad refuses link-local, cloud metadata and unspecified addresses, and the enterprise profile refuses loopback unless apps.allowLoopbackUpstreams is true. Private addresses always pass. |
A manifest can point the gateway at any internal service that strazad’s network reaches. | Review the address of every remote manifest before you publish it, and limit strazad’s outbound traffic at the network. | An egress allowlist for each governed MCP server. |
| A manifest is trusted as written. Straza checks no publisher signature on a server manifest you import or write. | A server runs with the access and the credential you give it, whatever the source of its manifest. | Review each manifest before you publish it, and set admin.secondPerson so that a change that widens access needs a second person to publish. |
Manifests verified against a publisher signature before install. |
| Audit records can be lost. Server records wait in a memory queue of 4,096 before the database takes them, and the client spool drops its oldest records past 32 MiB. | A crash, a kill before the stop finishes, a full queue in standalone, or a failed write of an admin, identity, authentication or approval record loses records. The chain cannot show a record that never reached it. | block, the enterprise default of governance.auditBackpressure, refuses a decision rather than run it without its record. Give strazad 30 seconds to stop, and watch straza_audit_lost_total, straza_audit_dropped_total and the loss marker of straza doctor. |
Not on the roadmap. |
| The hash chain cannot defeat the database owner. The chain proves that no record was edited or removed in place. | Someone who can write the database can rewrite every later record too, and a verify run inside that database finds the rewritten chain consistent. | A sink that keeps a copy of every record off the box, where that person cannot reach it. | Not on the roadmap. |
| Knowledge pack changes leave no audit record. Creating, binding, unbinding and deleting a pack writes nothing to the audit chain. | The chain cannot show who changed what an agent receives at check-in. | Grant identity:write, the area that covers packs, only to people and tokens you trust, and review strazactl packs list. |
Not on the roadmap. |
A few settings move these limits when you change them from their defaults, and Hardening lists every security setting with its default in both profiles.
Scale ceilings
One deployment of Straza also has ceilings on how much it carries. Each row gives the ceiling, the reason it exists and what to do as you approach it. Requirements and sizing gives the measured runs behind the numbers.
| Ceiling | Why it is there | What to do near it |
|---|---|---|
| A standalone server runs on one host, as one process. | It keeps its SQLite store and its embedded event bus in its own data directory, so a second replica would hold a second, separate store. The Helm chart refuses to render the standalone profile with more than one replica. | Move to the enterprise shape when you need a second replica. |
| 1,000 connected agents per strazad is the most any capped run held. | The run passed every check in 2 CPUs and 1 GB on SQLite, and no capped run went higher. | Above 1,000, give strazad more memory and processors or add enterprise replicas, and measure your own load. |
| The server’s audit queue holds 4,096 records in memory. | Each record waits there between its decision and the database write. | In standalone a full queue drops records and counts them in straza_audit_dropped_total. In enterprise, under block, a decision waits up to 25 seconds for room and is then refused. Keep the database reachable. |
| The chart’s 512 MiB limit is reached above about 250 server decisions a second while the database is down. | Under block, each waiting decision holds memory and its client’s request for up to 25 seconds. |
Raise the memory limit above your peak decision rate, or spread the load over more replicas. |
| A replica opens up to 16 Postgres connections, or 4 for each processor Go uses when that is more. | strazad bounds its connections, so a burst waits inside strazad instead of exhausting the database. | Keep Postgres max_connections, 100 by default, above 16 for each replica under the chart’s CPU limit of 1, plus your other clients. The chart’s autoscaler, when you turn it on, allows 10 replicas by default. |
| The client spool holds up to 32 MiB of parked records, each under 3 MiB. | It bounds the disk a client uses while strazad cannot be reached. | Past the cap the oldest parked records are dropped, and straza doctor reports the loss. Keep clients able to reach strazad. |
| 65,536 clients can hold the push stream open at one strazad. | events.pushEdgeMaxConns bounds the open push streams of one process. |
A client over the cap polls instead until a retry gets in. Raise the setting or add replicas. |
| The audit stream on NATS keeps 60 days and at most 2 GiB by default. | Unbounded, a full disk would stop strazad from publishing any event, kill-switch revocations included. | The stream drops its oldest records first. Keep events.auditStreamMaxBytes well below the NATS volume, 5Gi in the chart. |
A server manifest’s limits.cpu and limits.mem are stored and not enforced. |
strazad checks their format and nothing reads them yet. | Bound the server’s processors and memory in the runtime that runs it, such as its container or pod. |
The roadmap’s scale-out tier plans cells, independent deployments with their own database and event spine, as the unit of growth past one deployment.
Report anything that contradicts this page through Reporting a vulnerability.