Security
Security is a core design principle of Octipus. Every tool call, API request, and stored credential is protected by multiple layers of security.
Multi-User
Section titled “Multi-User”Octipus is multi-user by default. Every HTTP and WebSocket request must carry either a real session token (cookie, after login) or a personal octi_… api token. All requests run against scoped repositories with per-user (and per-org) isolation.
Tunable behaviors (via the Settings API):
| Setting | Default | Behavior |
|---|---|---|
multiuser.enforcePermissions | true | Deny cross-tenant reads/writes; collapses to 404 to avoid UUID enumeration. |
multiuser.orgWorkspaces | true | Per-org workspace scoping for repos and uploads. |
multiuser.rlsEnabled | false | Postgres row-level security. Opt-in — requires a non-superuser app role. |
multiuser.auditShadow | true | Mirror permission decisions into the audit log. |
Admins can use Act as (impersonation) on the Users page; the impersonation banner stays visible and every action is audit-logged with both the real and effective principal.
Authentication
Section titled “Authentication”Octipus supports four authentication methods:
JWT Sessions
Section titled “JWT Sessions”The primary interactive method. Users log in with credentials and receive a JWT token that authenticates subsequent requests.
- Tokens are issued on login and validated by the auth guard middleware
- Public paths (health checks, registration, login) bypass authentication
- Sessions are persisted across reloads via
SESSION_SECRET-signed cookies
Personal API Tokens (octi_…)
Section titled “Personal API Tokens (octi_…)”For MCP servers, CLI tools, the browser extension, and the TUI. Mint them in Settings → API Tokens in the web UI; they’re stored hashed in the api_tokens table and scoped to the issuing user.
- Format:
octi_<random>; shown once on creation - Sent as
Authorization: Bearer octi_…(HTTP) orapi_key(WebSocket) - Revocable from the same Settings page; deletion is immediate
- On startup the backend mints a special
mcp-bootstraptoken for the first active admin and writes it to~/.octipus/mcp-token(mode 600) so MCP clients can connect without manual setup — see MCP
Master Key — vault encryption root
Section titled “Master Key — vault encryption root”The MASTER_KEY is the vault encryption root, not an auth credential. HKDF derives per-user data-encryption keys from it; rotating it goes through scripts/rotate-vault-keys.ts.
- It does not authenticate HTTP/WS clients — every request uses a session token or a personal
octi_…api token - Rotating it makes existing vault entries unrecoverable, so treat it as permanent (see the master-key warning in Configuration Precedence)
WebAuthn Passkeys
Section titled “WebAuthn Passkeys”Hardware-backed passwordless authentication using the WebAuthn standard.
- Register a passkey from the Settings page
- Authenticate with your device’s biometric sensor or security key
- Supported by all modern browsers and operating systems
TOTP Two-Factor Authentication
Section titled “TOTP Two-Factor Authentication”Time-based One-Time Password (TOTP) for an additional layer of security.
- Set up via the Settings page with any authenticator app (Google Authenticator, Authy, etc.)
- Required on login once enabled
- Can be disabled through the API with proper authentication
Encrypted Vault
Section titled “Encrypted Vault”The vault provides AES-256-GCM encrypted credential storage for sensitive data like API keys, tokens, and passwords. The vault and database are the source of truth for all secrets — do not store credentials in .env files.
Features
Section titled “Features”- Per-skill access control: Credentials can be scoped to specific skills
- Per-agent access control: Credentials can be limited to specific agents
- Rotation support: Credentials can be rotated via the API without updating dependent configurations
- Template-based injection: Skills reference secrets using templates rather than raw values
Vault API
Section titled “Vault API”| Operation | Endpoint | Description |
|---|---|---|
| List | GET /api/vault | List all stored credentials |
| Store | POST /api/vault | Store a new credential |
| Update | PATCH /api/vault/:id | Update an existing credential |
| Delete | DELETE /api/vault/:id | Delete a credential |
| Rotate | POST /api/vault/:id/rotate | Rotate a credential’s value |
Permission System
Section titled “Permission System”Rule-Based Permission Engine
Section titled “Rule-Based Permission Engine”Tool permissions use a pattern-matching rule engine (inspired by claw-code-parity). Rules are evaluated in order: deny → allow → ask.
Syntax: tool_id(matcher)
| Pattern | Meaning | Example |
|---|---|---|
shell(*) | Wildcard — any shell command | Allow all shell use |
shell(git:*) | Prefix — commands starting with “git” | Allow git commands |
shell(git status) | Exact — only this command | Allow only git status |
Default rules:
{ "allow": ["shell(git:*)", "shell(ls:*)", "filesystem(*)", "knowledge(*)", "websearch(*)"], "deny": ["shell(rm -rf /:*)", "shell(dd if=/dev:*)", "shell(mkfs:*)"], "ask": ["shell(sudo:*)", "shell(docker:*)", "shell(systemctl:*)"]}Configure via Settings API: PUT /api/settings/permissions.rules
Three-Tier Permissions
Section titled “Three-Tier Permissions”Every tool action is governed by one of three permission levels:
| Level | Behavior | Example |
|---|---|---|
| ALLOW | Executes immediately | Reading files, searching the web |
| ASK | Pauses for user approval | Writing files, running commands |
| DENY | Blocked entirely | Destructive shell commands |
Permission Denial
Section titled “Permission Denial”When a user denies a permission prompt (or it times out), the agent is immediately stopped — it does not retry or try alternative approaches. The orchestrator returns control to the user with a friendly message referencing the original request.
Pre/Post Tool Hooks
Section titled “Pre/Post Tool Hooks”Hooks with trigger type tool_pre or tool_post run before/after tool execution:
- Pre-tool hooks can block execution (deny decision)
- Post-tool hooks can log, notify, or trigger downstream actions
- Match tools via
triggerConfig.toolPattern(wildcard, prefix, exact)
Permission Conditions
Section titled “Permission Conditions”Permissions can be further refined with conditions:
- Path patterns: Allow/deny based on file paths (e.g., allow writes only in
./workspace/) - Command patterns: Allow/deny based on command strings
- Time windows: Restrict operations to specific time ranges
- Rate limits: Limit how frequently a tool can be called
Secret Injection
Section titled “Secret Injection”The secret injector enables agents to use vault credentials without exposing raw values. Tool arguments can reference secrets using a template syntax:
{{secret:my-api-key}}When a tool call contains this template, the runtime:
- Looks up the secret
my-api-keyin the vault - Decrypts the value
- Substitutes it into the tool argument before execution
The raw secret value is never exposed to the LLM or included in conversation history.
Audit Logging
Section titled “Audit Logging”All security-relevant events are logged to the audit_log table:
- User authentication (login, logout, failed attempts)
- Permission requests and decisions
- Vault operations (create, update, delete, rotate)
- Tool executions with approval status
Each audit entry includes the user, action, resource, and timestamp for full traceability.