Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dallay/corvus/llms.txt

Use this file to discover all available pages before exploring further.

Security Philosophy

Corvus enforces security at every layer — not just the sandbox. The framework is designed with defense-in-depth:
1

Gateway Security

Pairing codes, bearer tokens, localhost-only binding by default
2

Autonomy Controls

Readonly, supervised, and full autonomy levels with explicit allowlists
3

Runtime Isolation

Native, Docker, or sandboxed execution (Landlock, Firejail, Bubblewrap)
4

Filesystem Scoping

Workspace-only access, forbidden path blocking, symlink escape detection

Gateway Security

The gateway server requires pairing and authentication by default:
[gateway]
port = 3000
host = "127.0.0.1"  # Localhost-only by default
require_pairing = true
allow_public_bind = false

# Rate limiting
pair_rate_limit_per_minute = 10
webhook_rate_limit_per_minute = 60
trust_forwarded_headers = false

# Idempotency
idempotency_ttl_secs = 300
idempotency_max_keys = 10000

Pairing Flow

1

Start Gateway

corvus gateway
A 6-digit pairing code is displayed in the console.
2

Exchange Code for Token

curl -X POST http://127.0.0.1:3000/pair \
  -H "X-Pairing-Code: 123456"
Returns a bearer token.
3

Use Bearer Token

curl -X POST http://127.0.0.1:3000/webhook \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"message": "Hello"}'

Configuration Fields

gateway.port
number
default:3000
Gateway port. Use 0 for random port (security-hardened mode).
gateway.host
string
default:"127.0.0.1"
Gateway host binding:
  • 127.0.0.1: Localhost only (default, secure)
  • 0.0.0.0: All interfaces (requires tunnel or allow_public_bind)
gateway.require_pairing
boolean
default:true
Require pairing code exchange before accepting requests.
gateway.allow_public_bind
boolean
default:false
Allow binding to non-localhost without an active tunnel.
Only enable this if you have proper network isolation (firewall, VPN).
gateway.pair_rate_limit_per_minute
number
default:10
Maximum /pair requests per minute per client.
gateway.webhook_rate_limit_per_minute
number
default:60
Maximum /webhook requests per minute per client.
gateway.trust_forwarded_headers
boolean
default:false
Trust proxy-forwarded client IP headers (X-Forwarded-For, X-Real-IP).Only enable behind a trusted reverse proxy.
gateway.idempotency_ttl_secs
number
default:300
TTL for webhook idempotency keys (5 minutes).

Autonomy Levels

Corvus supports three autonomy levels:
No state-modifying actions. Agent can only:
  • Read files
  • Recall memories
  • Execute read-only shell commands
[autonomy]
level = "readonly"

Autonomy Configuration

[autonomy]
level = "supervised"
workspace_only = true

# Command allowlists
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep"]

# Path blocklists
forbidden_paths = [
  "/etc", "/root", "/home", "/usr", "/bin", "/sbin",
  "/lib", "/opt", "/boot", "/dev", "/proc", "/sys",
  "/var", "/tmp",
  "~/.ssh", "~/.gnupg", "~/.aws", "~/.config"
]

# Rate limits
max_actions_per_hour = 20
max_cost_per_day_cents = 500

# Risk controls
require_approval_for_medium_risk = true
block_high_risk_commands = true

# Tool approval overrides
auto_approve = ["file_read", "memory_recall"]
always_ask = []  # Always require approval for these tools

Configuration Fields

autonomy.level
string
default:"supervised"
Autonomy level: readonly, supervised, or full.
autonomy.workspace_only
boolean
default:true
Restrict file access to workspace directory only.
  • Blocks 14 system directories
  • Blocks 4 sensitive dotfiles (.ssh, .gnupg, .aws, .config)
  • Prevents null byte injection
  • Detects symlink escape attempts
autonomy.allowed_commands
string[]
Allowlist of shell commands the agent can execute.
autonomy.forbidden_paths
string[]
Blocklist of paths the agent cannot access. Default: ["/etc", "/root", "/proc", "/sys", "~/.ssh", "~/.gnupg", "~/.aws"]
autonomy.max_actions_per_hour
number
default:20
Maximum actions per hour (rate limit).
autonomy.max_cost_per_day_cents
number
default:500
Maximum cost per day in cents (budget limit).
autonomy.require_approval_for_medium_risk
boolean
default:true
Require explicit approval for medium-risk shell commands.
autonomy.block_high_risk_commands
boolean
default:true
Block high-risk shell commands even if allowlisted.
autonomy.auto_approve
string[]
default:["file_read","memory_recall"]
Tools that never require approval (read-only tools).
autonomy.always_ask
string[]
default:[]
Tools that always require interactive approval, even after “Always” confirmation.

Runtime Configuration

Corvus supports two runtime modes:
Direct execution on the host system:
[runtime]
kind = "native"
Best for:
  • Development
  • Trusted environments
  • Maximum performance

Docker Runtime Settings

runtime.kind
string
default:"native"
Runtime kind: native or docker.
runtime.docker.image
string
default:"alpine:3.20"
Docker image for shell command execution.
runtime.docker.network
string
default:"none"
Docker network mode:
  • none: No network access (most secure)
  • bridge: Bridge network
  • host: Host network (not recommended)
runtime.docker.memory_limit_mb
number
default:512
Memory limit in MB. None = no explicit limit.
runtime.docker.cpu_limit
number
CPU limit (number of cores). None = no explicit limit.
runtime.docker.read_only_rootfs
boolean
default:true
Mount root filesystem as read-only.
runtime.docker.mount_workspace
boolean
default:true
Mount workspace into /workspace inside the container.
runtime.docker.allowed_workspace_roots
string[]
default:[]
Optional allowlist for workspace mount validation.

OS-Level Sandboxing

Additional sandboxing beyond Docker:
[security.sandbox]
enabled = true  # Auto-detect best available
backend = "auto"  # "auto", "landlock", "firejail", "bubblewrap", "docker", "none"

# Custom Firejail arguments
firejail_args = ["--net=none", "--nosound"]
security.sandbox.enabled
boolean
Enable OS-level sandboxing:
  • None: Auto-detect (default)
  • true: Force enable
  • false: Disable
security.sandbox.backend
string
default:"auto"
Sandbox backend:
  • auto: Auto-detect best available (default)
  • landlock: Linux kernel LSM (native, requires Linux 5.13+)
  • firejail: User-space sandbox
  • bubblewrap: User namespaces
  • docker: Docker container isolation
  • none: No OS-level sandboxing

Resource Limits

Limit resource usage for command execution:
[security.resources]
max_memory_mb = 512
max_cpu_time_seconds = 60
max_subprocesses = 10
memory_monitoring = true
security.resources.max_memory_mb
number
default:512
Maximum memory in MB per command.
security.resources.max_cpu_time_seconds
number
default:60
Maximum CPU time in seconds per command.
security.resources.max_subprocesses
number
default:10
Maximum number of subprocesses.
security.resources.memory_monitoring
boolean
default:true
Enable memory usage monitoring.

Audit Logging

Tamper-evident audit logs:
[security.audit]
enabled = true
log_path = "audit.log"  # Relative to ~/.corvus/
max_size_mb = 100
sign_events = false  # HMAC signing for tamper evidence
security.audit.enabled
boolean
default:true
Enable audit logging.
security.audit.log_path
string
default:"audit.log"
Path to audit log file (relative to ~/.corvus/).
security.audit.max_size_mb
number
default:100
Maximum log size in MB before rotation.
security.audit.sign_events
boolean
default:false
Sign events with HMAC for tamper evidence.

Secrets Encryption

Encrypt API keys in config file:
[secrets]
encrypt = true  # Default: encrypt all secrets
secrets.encrypt
boolean
default:true
Enable encryption for API keys and tokens in config.toml.Encrypted values are prefixed with enc: and are tied to the local machine via a key file in ~/.corvus/.

Security Checklist

✅ Binds 127.0.0.1 by default✅ Refuses 0.0.0.0 without tunnel or explicit allow_public_bind = true
✅ 6-digit one-time code on startup✅ Exchange via POST /pair for bearer token✅ All /webhook requests require Authorization: Bearer <token>
workspace_only = true by default✅ 14 system dirs + 4 sensitive dotfiles blocked✅ Null byte injection blocked✅ Symlink escape detection via canonicalization
✅ Gateway refuses public bind without active tunnel✅ Supports Tailscale, Cloudflare, ngrok, or custom tunnel

Complete Example

# Gateway security
[gateway]
port = 3000
host = "127.0.0.1"
require_pairing = true
allow_public_bind = false
pair_rate_limit_per_minute = 10
webhook_rate_limit_per_minute = 60

# Autonomy controls
[autonomy]
level = "supervised"
workspace_only = true
allowed_commands = ["git", "npm", "cargo"]
forbidden_paths = ["/etc", "/root", "~/.ssh"]
max_actions_per_hour = 20
max_cost_per_day_cents = 500
require_approval_for_medium_risk = true
block_high_risk_commands = true
auto_approve = ["file_read", "memory_recall"]

# Runtime isolation
[runtime]
kind = "docker"

[runtime.docker]
image = "alpine:3.20"
network = "none"
memory_limit_mb = 512
cpu_limit = 1.0
read_only_rootfs = true
mount_workspace = true

# OS-level sandboxing
[security.sandbox]
enabled = true
backend = "auto"

# Resource limits
[security.resources]
max_memory_mb = 512
max_cpu_time_seconds = 60
max_subprocesses = 10

# Audit logging
[security.audit]
enabled = true
log_path = "audit.log"
max_size_mb = 100
sign_events = true

# Secrets encryption
[secrets]
encrypt = true

Tunnel Configuration

Expose gateway securely using tunnels:
[tunnel]
provider = "cloudflare"

[tunnel.cloudflare]
token = "your-tunnel-token"

Next Steps

Provider Configuration

Set up AI model providers and API keys

Channel Configuration

Enable messaging platform integrations

Build docs developers (and LLMs) love