Security model
Somora runs on your machine and uses provider authentication you've already set up (Claude Code subscription, Codex CLI subscription, or an API key for a local LLM). The interesting security question is: what prevents an agent running through one of those providers from doing something it shouldn't — reading files outside its memory scope, pulling other context from the host's setup, calling unauthorised tools?
This doc summarises the defenses each engine adapter installs.
Trust boundary
you ──► CLI/HTTP ──► somora-server ──┬─► claude-cli engine ──► Claude Code binary ──► Anthropic API
├─► codex-cli engine ──► bundled Codex ──► OpenAI API
├─► grok-cli engine ──► Grok Build CLI (ACP) ──► xAI API
└─► openai-compatible ──► fetch /v1/chat/... ──► local LLM or cloudThe somora server is the boundary. Inside the somora server we trust ourselves; outside (the spawned CLI binaries, the LLM endpoints) we don't. Each engine adapter takes care to keep host-context out of the prompt and built-in tools out of the model's reach.
claude-cli adapter
The Anthropic Agent SDK and the underlying Claude Code binary auto-load a fair amount of host context by default — the Claude.ai account's connectors (Gmail, Drive, Calendar) as MCP servers, project-scoped auto-memory under ~/.claude/projects/<cwd>/memory/*, settings files, CLAUDE.md walk-up, and so on. None of that should leak into a somora agent's prompt.
Six-layer defense in src/engine/claude-cli.ts:
settingSources: []— disablessettings.json/CLAUDE.mdloading from user / project / local scope.tools: []— empty allowlist of built-in tools.disallowedTools: KNOWN_ACCOUNT_TOOLS— explicit deny-list of the six known Claude.ai connector auth tools (mcp__claude_ai_Gmail__authenticateet al). They sometimes appear in the SDK's tool list anyway — the adapter logsengine.tools_leakedif a new one shows up.canUseToolgate — a per-call permission callback that allows onlymcp__somora__*tool names (plusmcp__somora-<name>__*for configured external-server proxies); everything else is denied. A CLI session recorded under an earlier MCP server name is restarted once on its next turn, with the session history replayed, and shows asession restartedengine row.managedSettings: { autoMemoryEnabled: false }— disables the project-memory auto-loader. Without this,~/.claude/projects/<cwd>/memory/*files leak into the system prompt.strictMcpConfig: true— only the MCP servers somora passes exist for the session. Without it the claude.ai account connectors (Gmail, Calendar, Drive) are listed as "needs-auth" and mentioned to the model even with their tools denied; with it they do not appear at all.
What the SDK's init message lists as skills, slash_commands and agents is SDK-side inventory: with a plain-string systemPrompt and settingSources: [] none of it reaches the model (verified by asking the model to list everything it was told about — only the somora tools and ToolSearch came back).
Diagnostic logs you'll see:
engine.init with full tool list + mcp_servers (sanity check)
engine.tools_leaked if any tool slipped past the deny-list
engine.mcp_servers_leaked if any account-MCP shows up beyond ourscodex-cli adapter
Codex CLI ships with a long list of default-on built-in features — shell command execution, file editing (apply_patch), browser automation, computer use, image generation, JS REPL, web search, plus context loaders (config.toml, AGENTS.md walk-up, personality, memories). None belong inside a somora agent.
Defense in src/engine/codex-thread-config.ts (the config overlay every thread starts with) and src/engine/codex-home.ts:
- Pinned binary. Codex is a bundled, exact-version dependency. A Codex release cannot change the tool surface underneath somora; the pin is bumped deliberately and the overlay re-audited against
somora codex features list. - Feature lock-down as thread config: shell and exec tools, browser and computer use, image generation, apps, multi-agent (
multi_agent,multi_agent_v2,agents.enabled), personality, mentions, hooks and plugins, goals, fast mode,view_image,skill_search; plusweb_search="disabled",tools.update_plan.enabled=false,tools.experimental_request_user_input.enabled=false, bundled skills off,project_doc_max_bytes=0andproject_root_markers=[](no AGENTS.md walk-up),notify=[],mcp_servers={}. - Own Codex home. Codex runs with
CODEX_HOME=~/.somora/codex-home(like claude-cli's~/.somora/claude-home). Onlyauth.jsonis mirrored from~/.codex, so the user'sconfig.toml, MCP servers, hooks, plugins, skills and thread store never reach an agent. - Code Mode. The GPT-5.6 family and GPT-6 run tool calls through Codex's code-mode host: the model writes JavaScript that calls
tools.somora.<tool>(...). Verified 2026-09-05: that sandbox has norequire,process,fetchor filesystem — it can only bundle calls to the tools somora exposes, which run on the somora server under the same policies as on every other engine. - Known residual:
apply_patchcannot be switched off — the model catalog marks gpt-5.x withapply_patch_tool_type: "freeform"and Codex has no config key for it. The threelist_mcp_resource*helpers only read MCP resources, and no MCP server is configured. - Sandbox: somora is the sandbox. Threads start with
approvalPolicy: neverandsandbox: danger-full-accessso somora's own tools (path blacklist, per-resource policy) are never blocked by Codex's approval flow; Codex's built-in file/shell tools are locked down above instead. Approval requests that arrive anyway are declined.
tool_search and tool_suggest stay enabled on purpose — codex routes MCP tool calls through these meta-tools as the discovery/dispatch layer. Disabling them silently breaks every MCP tool call.
openai-compatible adapter
This one's the simplest from a leak standpoint: somora opens a fresh HTTPS connection to the configured baseUrl, sends only the turn-specific messages and tools, and gets a response. There's no host-context auto-loading because there's no CLI subprocess to inherit from. The only attack surface is the LLM endpoint itself, which is your choice (local Ollama, vendor API, etc.).
One more field goes along by default: the standard OpenAI user string, filled with <agent>/<session id> for chat turns and <agent>/rem, <agent>/deep, lucid/<pass>, <agent>/compaction, <agent>/analyze_file for background workers — so a gateway in between (LiteLLM, a vLLM router) can attribute spend per agent. Agent names and session ids are the only content; no message text beyond what the turn sends anyway. If a provider must not see them, set sendUserTag: false on that provider (models.md).
The agent-loop in src/engine/openai-compatible.ts caps tool-call rounds (agentLoop.maxRounds, default 8) and per-tool timeout (agentLoop.toolCallTimeoutMs, default 30 s) to prevent runaway loops.
Memory tool scope
All memory_* write tools are hard-scoped to ~/.somora/agents/<name>/memory/:
- Slug regex:
^[a-z0-9][a-z0-9_-]*$. No path separators, no uppercase, no hidden directories. - Vault writes are NOT exposed to agents. The wiki layer is written exclusively by the Deep phase (memory→wiki consolidation) and the Lucid phase (cleanup) — both server-side workers, scoped to the configured wiki subfolder. Everything else in the vault stays read-only from somora's perspective.
Even a buggy or adversarial model output cannot escape an agent's own memory directory through memory_write/memory_edit/memory_delete.
What somora does NOT defend against
- Compromised provider. If your Anthropic/OpenAI/local-LLM endpoint is hostile, somora can't help — it's just passing your prompt to it and getting a response.
- Local filesystem access by tools.
memory_*tools read your own memory files; that's the design. If you write secrets into a memory note and then ask an agent about them, the model sees the secret. - Network egress. somora doesn't sandbox the spawned binaries. Codex threads run with
sandbox: danger-full-access(somora's own tool policies are the sandbox, see above), claude-cli has no sandbox flag at all. If the binary phones home outside your knowledge, somora won't catch it. - Multi-tenant deployment. somora binds to
127.0.0.1and assumes you're its only user. Putting it behind a network reverse proxy without proper auth would expose your agents to anyone who can reach the proxy. - The server log is readable over the API.
GET /logsserves the tail of somora's own log so the web client can show it, and the log records prompts' metadata, tool names, paths, agent and session names — not the message text, but enough to profile the work. It is bounded to a day's file and never takes a path, so it cannot read arbitrary files; it is not, however, a secret. Anyone who can reach the port can read it, which is the same trust assumption as every other route.
Reporting issues
For now: open a GitHub issue with the security label. Don't include secrets in the report.