Security & Authentication
Zubo is designed for single-owner, self-hosted operation. All data stays on your machine, and no external services are contacted unless you explicitly configure them. This page covers every security feature in the system: API authentication, tool permissions, secret management, sandboxing, rate limiting, and access control.
API Authentication
By default, API authentication is disabled. This is appropriate when Zubo is running on localhost for a single user. If you expose the web chat port to a network or the internet, you should enable authentication.
Enabling Authentication
zubo config set auth.enabled true
Once enabled, all /api/* endpoints require a valid API key in the Authorization header.
Creating API Keys
zubo auth create-key [label]
This generates a cryptographically random 64-character key. The raw key is displayed only once — copy it immediately. Before storage, the key is hashed with SHA-256, so the plaintext value cannot be recovered from the database.
Using API Keys
Include the key in the Authorization header on every request:
curl -H "Authorization: Bearer <your-key>" http://localhost:3000/api/chat
Managing Keys
- List keys:
zubo auth list-keys— shows label, creation date, and last-used timestamp (never the raw key) - Delete a key:
zubo auth delete-key <id>— immediately revokes the key - Dashboard: Keys can also be managed in Settings → Data section of the web dashboard
- API: Programmatic management is available via the
/api/keysendpoints
Session Tokens
Session tokens provide short-lived authentication for the web dashboard when API authentication is enabled.
- TTL: 1 hour
- Usage: Single-use — each token can only be used once
- Generation:
POST /api/auth/session(requires a valid API key) - Purpose: After authenticating with your API key, the dashboard receives a session token for subsequent requests, avoiding repeated API key transmission over the wire
Tool Permissions
Every tool in Zubo has a permission level that controls how it executes. There are three levels:
| Level | Behavior | Example Tools |
|---|---|---|
auto |
Executes immediately with no user confirmation | datetime, memory_write, memory_search, web_search, url_fetch |
confirm |
Requires explicit user approval before execution | shell, file_write, secret_delete, twitter_posts |
deny |
Blocked entirely — the tool cannot be used | (custom blocked tools configured by the user) |
Confirmation Flow
When the agent calls a tool with confirm permission, the following flow occurs:
- The agent invokes a
confirm-level tool (e.g.,shell) - The executor generates a random UUID confirmation token with a 10-minute TTL
- The tool returns a
CONFIRMATION REQUIREDmessage containing the token - The agent describes the intended action to the user and asks for approval
- If the user approves, the agent retries the tool call with
_confirmTokenincluded in the input - The server validates that the token matches the specific tool name and has not expired
- The tool executes normally
This design prevents the LLM from spoofing confirmations — only the server can issue valid confirmation tokens, and each token is bound to a specific tool invocation.
Secret Management
Secrets (API keys, tokens, passwords) are stored securely in the local SQLite secrets table. The agent can use secrets by name but never sees their actual values in conversation context.
Storing Secrets
There are three ways to store a secret:
- Chat: Tell Zubo directly —
"Store my GitHub token: ghp_abc123xyz" - Tool: The
secret_settool can be called programmatically - Dashboard: Navigate to Settings → Secrets and use the form
Accessing Secrets in Skills
User-installed skills can access secrets via environment variables:
const token = process.env.ZUBO_SECRET_GITHUB_TOKEN;
Only secrets explicitly declared in the skill manifest are passed to the skill process.
Managing Secrets
- Dashboard: View masked values (
••••••••), click “Reveal” to show the actual value, click “Edit” to update, or “Delete” to remove - Naming: Secret names must match the pattern
[a-z0-9_]+(lowercase alphanumeric and underscores only) - CLI: Tell Zubo
"list my secrets"or"delete the github_token secret"
Skill Sandboxing
User-installed skills (stored in ~/.zubo/workspace/skills/) run in isolated Bun subprocesses. This provides a security boundary between the main Zubo process and third-party skill code. Built-in tools are not sandboxed — they run in the main process.
Sandbox Features
- Separate process: Each skill execution spawns a new subprocess with no access to the parent process memory or state
- Timeout enforcement: Skills are terminated if they exceed the configured timeout (default: 30 seconds)
- Minimal environment: Only explicitly declared secrets are passed as environment variables — the skill cannot access the full system environment
- Exit code handling: Non-zero exit codes are caught and reported as tool errors
Configuration
zubo config set sandbox.enabled true
zubo config set sandbox.timeoutMs 30000
Skills installed from the Zubo skill registry are always sandboxed, regardless of the global setting.
Shell Command Safety
The shell tool includes a blocklist of dangerous command patterns. Any command matching these patterns is rejected before execution:
rm -rf /,rm -rf ~,rm -rf *— destructive recursive deletionmkfs— filesystem formattingddwriting to/dev/— raw device access:(){:|:&};:— fork bombskill -1,kill -9 1— killing init/system processeschmod 777 /— open permissions on rootshutdown,reboot,halt— system power commands
Environment Sanitization
Before executing any shell command, the environment is sanitized: API keys, tokens, and secrets are stripped from the environment variables passed to the child process. This prevents accidental leakage of credentials through commands like env or printenv.
Output Limits
- stdout: Truncated at 50 KB
- stderr: Truncated at 10 KB
This prevents runaway commands from consuming excessive memory in the agent context.
File Access Restrictions
The file_read and file_write tools are restricted to the user’s home directory. Path traversal attacks using .. are blocked — all paths are resolved and validated before access.
Blocked Paths (Read and Write)
~/.ssh/— SSH private keys and configuration~/.aws/credentials— AWS credential files.envfiles — environment variable files containing secrets~/.zubo/config.json— Zubo configuration (contains API keys)- Private key files:
*.pem,*.key
Additional Write Blocks
The file_write tool additionally blocks writing to shell configuration files:
.bashrc,.bash_profile.zshrc,.zprofile.profile
This prevents the agent from accidentally or maliciously modifying your shell startup scripts.
HTTP Request Safety
The http_request tool blocks requests to private and internal IP ranges, preventing Server-Side Request Forgery (SSRF) attacks:
| Range | Description |
|---|---|
127.0.0.0/8 | Localhost / loopback |
10.0.0.0/8 | Private network (Class A) |
172.16.0.0/12 | Private network (Class B) |
192.168.0.0/16 | Private network (Class C) |
169.254.0.0/16 | Link-local addresses |
0.0.0.0 | Unspecified address |
This prevents the agent from being tricked into making requests to internal services, cloud metadata endpoints (e.g., 169.254.169.254), or other hosts on your local network.
Rate Limiting
Zubo includes per-IP sliding-window rate limiting to prevent abuse when the API is exposed to a network.
Defaults
- Chat requests: 60 per minute
- File uploads: 10 per minute
Configuration
zubo config set rateLimit.chatPerMinute 30
zubo config set rateLimit.uploadPerMinute 5
Behavior
When a client exceeds the rate limit, the server responds with 429 Too Many Requests and includes a Retry-After header indicating how many seconds to wait before retrying.
Channel Access Control
Each messaging channel supports an allowlist to restrict who can interact with Zubo. When the allowlist is empty (the default), anyone who can reach the channel can send messages.
| Channel | Config Field | Value Format |
|---|---|---|
| Telegram | allowedUsers | User ID numbers (e.g., [123456789]) |
| Discord | allowedUsers | User ID strings (e.g., ["98765432109876543"]) |
| Slack | allowedUsers | User ID strings (e.g., ["U01ABC2DEF"]) |
allowedNumbers | Phone numbers (e.g., ["+15551234567"]) | |
| Signal | allowedNumbers | Phone numbers (e.g., ["+15559876543"]) |
Messages from users not on the allowlist are silently ignored. Always configure allowlists for channels exposed to the public internet.
Sub-Agent Security
When the main agent delegates tasks to sub-agents, several security constraints are enforced:
- Restricted tool access: Delegated agents can only use tools explicitly listed in their
AGENT.mdmanifest file - Max delegation depth: 2 levels deep — this prevents infinite recursion or runaway delegation chains
- No further delegation: Sub-agents cannot use the
delegatetool to create their own sub-agents - No management access: Sub-agents cannot access the
manage_agentsordelegatetools - Isolated sessions: Each delegation runs in a separate session context, so sub-agents cannot read or modify the parent agent’s conversation state
Data Security
All Zubo data is stored locally on your machine in the ~/.zubo/ directory. Nothing is sent to external servers unless you explicitly configure an LLM provider or integration.
- Database: SQLite with WAL (Write-Ahead Logging) mode for crash-safe operation
- Automatic backups: Daily backups are created automatically in
~/.zubo/workspace/backups/, with the last 7 backups retained - Manual export: Run
zubo exportto export your data — this excludes secrets and API keys by default - Excluded from exports: The
secretsandapi_keystables are always excluded from exports to prevent accidental credential leakage - Budget controls: Set daily and monthly spending limits to prevent surprise bills. Zubo tracks token usage and estimated costs per model, with configurable warning thresholds. See Budget Controls in the configuration docs.
Logging
Zubo uses structured logging with automatic redaction of sensitive information.
Automatic Redaction
Any log entry containing fields named keys, values, secrets, passwords, tokens, or credentials will have their values replaced with *** before being written to disk.
Log Levels
debug— Verbose output for troubleshootinginfo— Normal operational messages (default)warn— Potential issues that don’t prevent operationerror— Failures that need attention
Log Location and Access
- File:
~/.zubo/logs/zubo.log - View logs:
zubo logs - Follow logs:
zubo logs --follow(streams new entries in real time)
Best Practices
- Enable API auth if you expose the web chat port to a network — run
zubo config set auth.enabled trueand create at least one API key - Always set allowedUsers for public-facing channels (Telegram, Discord, Slack) to prevent unauthorized access
- Use the confirmation system — do not bypass it by setting dangerous tools to
autopermission - Store secrets via the agent or dashboard, never hardcode them in skill source files or environment variables
- Review skill code before installing from the registry — sandboxing limits damage but does not eliminate all risk
- Set rate limits appropriate for your use case, especially if the API is network-accessible
- Check logs regularly for suspicious activity — use
zubo logsto review recent entries - Use
zubo exportfor safe backups — exports automatically exclude secrets and API keys - Rotate API keys periodically — delete old keys with
zubo auth delete-keyand create fresh ones - Keep Zubo updated to receive the latest security patches and improvements