SafetyCard Request a review

Kortix (Suna)

Open-source general AI agent / 'AI Management System' with sandboxed browser, shell and files

github.com/kortix-ai/suna · 2026-10-03 · 52b9ec9

Defense-in-depth score

3.2 / 10

Kortix runs every session in a remote sandbox and has unusually sophisticated building blocks — server-side connector credentials, hash-bound human approvals, network-enforced secret handles, and an agents-as-principals permission model. But the starter project ships the default agent with every grant set to 'all', tool permission 'allow' and connector approvals off, so a prompt-injected session can read plaintext secrets, act in every connected app and push to the default branch with no human involved. The change-request governance guard is also not tamper-resistant.

Safest setup

Kortix runs every session in a remote sandbox, keeps connector credentials on the server and records actions in an audit log. The starter project gives its default agent every grant, no approval step and open network access, so the safest setup narrows those grants, turns on the approval and secret-handle options Kortix already has, and limits the sandbox network yourself.

SetupHowWhat it gives you
Narrowly scoped app accountsConnect each app with an account or token limited to the data and actions this project needs, read-only where the task allowsThe app provider itself refuses anything outside that access, whatever a session asks for C1
A narrowed agent grantOn the kortix agent in kortix.yaml, replace all for connectors, secrets and kortix_permissions with lists of what the project uses, leaving out project.gitops.merge and project.gitops.ref.anyEach session reaches only the apps, secrets and project actions you listed, and its pushes stay on its own branch C1
Connector approvalsSet the project's connector policy mode to riskA signed-in person approves each connector write, bound to its exact arguments C2
Network-enforced secretsStore each secret with egress delivery, listing the HTTPS hosts that use itThe sandbox holds only a handle, and the real value reaches only the hosts you listed C8
A blocking spend budgetAdd an LLM gateway budget for the project with a limit_usd and the default block actionModel spend stops at a ceiling you set for each period C10
Marketplace off when unusedTurn the marketplace feature flag off for projects that don't install community itemsCommunity items stop reaching the project through one-click installs C7
A sandbox egress allowlistConfigure the sandbox provider's network policy so session sandboxes reach only the hosts your tasks needA narrow path for data to leave, whatever runs inside the sandbox C4
Reviewed shared configurationRead changes to agent prompts, skills, memory and harness config before they reach the default branchInstructions that every later session loads come only from changes a person has read C6

Approving with confidence

  • Read each prompt and approve connector calls one at a time; the argument preview is shortened and redacted, so approve calls whose purpose you recognise.
  • The approval covers connector calls only; shell commands and direct network requests from the sandbox are bounded by the grant and network steps above.

Handling data

  • Secrets on the default environment-variable delivery are readable by every process in the session sandbox, extensions included; treat sandbox output like the secrets it can hold.
  • Audit rows are written asynchronously and the oldest can be dropped under load; keep provider-side logs for the apps you connect as well.

Key gaps (3)

  1. The sandbox shell runs with OpenCode permission 'allow' and connector policy defaults to allow_all, so no consequential action crosses an approval gate. C2 · Approval gates
  2. A hijacked default session combines untrusted web/connector content, plaintext secrets and open egress plus irreversible actions with no human in the loop. C5 · Untrusted input blast radius
  3. Extensions (OpenCode plugins, MCP servers, marketplace items) run as the sandbox user with the full environment, session token and plaintext secrets. C7 · Third-party extensions

Criteria

C1 Identity & least privilege

0.25 / 1.00

Each session gets its own Kortix token bound to one project and one session, and with the 'agents as principals' model (on by default) an agent's API authority is its kortix.yaml grant intersected with a role ceiling, with member management, project deletion and credential issuance reserved for humans. Connector credentials stay on the server. But the starter agent ships with every grant set to 'all', every process in the sandbox receives the session token and all plaintext project secrets, and the change-request governance guard that protects agent grants is not tamper-resistant, which caps this criterion.

C2 Approval gates

0.25 / 1.00

Nothing asks a human before the default agent acts. The starter OpenCode config sets every tool permission to 'allow', so shell, file edits and web access run unprompted, and the connector gateway's policy mode defaults to 'allow_all', so sending email or calling any connected app runs without approval. Kortix does have a well-built approval path for connector calls when a project opts into 'risk' mode: writes require a human, the approval is bound to a hash of the exact arguments, only a signed-in human (never the agent's own session) can approve, and argument-level rules can allow, gate or block. Even then the sandbox shell and its open network bypass the gate entirely.

C3 Tool & action scoping

0.20 / 1.00

The default agent's main tools are general-purpose: an unrestricted shell, file editing and web fetching inside the sandbox, and every connected app's full action set. There are a few real in-code bounds — the git proxy keeps a session's pushes on its own branch unless its grant says otherwise, the memory tool checks resolved paths, and connector policies can carry argument conditions — but argument conditions are opt-in, and the starter grant includes the scope that lifts the git branch restriction. Everything is enabled by default.

C4 Code-execution isolation

0.65 / 1.00

All model-driven code runs in a per-session sandbox created on a remote provider (Daytona by default), never on the Kortix server, and there is no fallback to host execution: the provider list only contains remote services and creation fails without a project snapshot. Inside, the agent user has passwordless sudo, the box has unrestricted outbound network, the session token and plaintext project secrets are in its environment, and boxes are never auto-deleted. The paired-computer connector is a documented path that runs commands on a user's own machine.

C5 Untrusted input blast radius

0.00 / 1.00

The default agent reads web pages, search results, connector data such as inboxes, and Slack threads, and nothing in the code distinguishes that content from the user's instructions or restricts what happens after it is read. In the same session it holds every project secret as a plain environment variable, every connected app, unrestricted outbound network and the ability to push to the default branch, all without a human approval. A successful prompt injection can therefore both exfiltrate data and take irreversible actions unattended. Inbound triggers are reasonably fenced (Slack requires linked project members, webhooks are signed, inbound email is off by default).

C6 Memory, context & configuration integrity

0.25 / 1.00

Project memory is plain files under memory/ in the project's git repo, written by a path-checked memory tool and not auto-injected, so every change is a versioned commit that can be inspected and reverted. Agent governance (kortix.yaml agents and triggers) needs a human to merge a change request. But agent prompts, skills, memory and harness config (plugins, MCP servers, tool permissions) are not governance keys, the default agent can merge its own change requests, and it can push straight to the default branch, so a poisoned instruction can become permanent shared configuration for every user of the project without review.

C7 Third-party extensions

0.15 / 1.00

Third-party code reaches sessions in two ways: OpenCode plugins, tools and MCP servers declared in the project's harness config, and the marketplace (on by default), which starts an agent session that clones a community item's source and wires it into the project. The marketplace design document promises a lock file with content hashes, but the code says that engine was removed, so nothing is pinned or hash-checked. Extensions run inside the session sandbox as the same user, with the full environment including the session token and plaintext secrets, and the default agent can add them itself and merge or push the change.

C8 Secrets & sensitive-data protection

0.50 / 1.00

Secrets are stored encrypted and connector credentials and (by default) LLM provider keys never enter the sandbox. Kortix also offers a strong per-secret option where the sandbox holds only a handle and a proxy substitutes the real value on approved hosts. But a new secret defaults to plain environment-variable delivery, and the starter agent is granted every secret, so the model can read them directly. Telemetry is off unless a Sentry DSN is set and excludes PII; argument previews and audit summaries are redacted.

C9 Audit & traceability

0.60 / 1.00

Kortix keeps a structured audit log in its own database: API actions, connector calls (with approval status and an argument digest), and OpenCode tool events relayed from each sandbox, each tagged with actor type, agent, on-behalf-of human and delegation depth. That is a solid record for reconstructing who did what. The limits are durability and trust in the in-sandbox feed: rows are buffered in memory and the oldest are dropped under overload, and the tool-event relay runs inside a sandbox where the agent has root.

C10 Limits & kill switch

0.33 / 1.00

Runaway sessions are bounded mainly by wall-clock: each observed turn gets a 4-hour renewable grant and an absolute 24-hour ceiling enforced by the control plane, and stopping a session stops the whole provider sandbox, which kills everything inside it. There is no step cap in the starter agent, and LLM spend budgets exist only if an operator sets them. Agents can start other sessions, which get their own limits, and triggers or reminders keep running after a single session is stopped.