Security Model
Security is compiled into EdgeCrab — not runtime configuration switches. Every tool execution passes through a 7-layer defense stack before any file is read, any command is run, or any URL is fetched.
Threat Model
Section titled “Threat Model”EdgeCrab is an autonomous agent: it reads files, runs shell commands, and makes HTTP requests on your behalf. The primary risks are:
Risk Vector-------------------------------------------------------Path traversal LLM reads /etc/passwd or ~/.ssh/id_rsaSSRF Web tool fetches 169.254.169.254 (cloud IMDS)Command injection Malicious file content escapes to shell argsSecret exfiltration LLM output contains API keys from read filesPrompt injection Web page / file contains hidden LLM instructionsUnsafe approval Agent runs destructive op without user reviewLayer 1 — Path Safety (path_jail.rs)
Section titled “Layer 1 — Path Safety (path_jail.rs)”Every file read / write / list / search passes through path_jail:
- Resolve all symlinks and collapse
..(canonicalize) - Verify the canonical path starts with one of the allowed roots
- Reject the call if it falls outside allowed roots
The active workspace root is always allowed. Add extra roots explicitly in config.yaml:
tools: file: allowed_roots: - /Users/you/projects/myapp # only this projectThis policy is enforced at runtime by the shared path resolver used by
file tools, local vision image reads, and @file / @folder context refs.
It is not a general terminal sandbox: shell commands can still access any
path the selected execution backend can reach.
Layer 2 — SSRF Guard (url_safety.rs)
Section titled “Layer 2 — SSRF Guard (url_safety.rs)”All outbound HTTP calls (web search, web extract, web crawl, browser navigation) resolve the hostname to IPs and check those resolved IPs against a blocklist — preventing DNS-rebinding bypasses.
Blocked address space:
| Range | Category |
|---|---|
10.0.0.0/8 | RFC 1918 private |
172.16.0.0/12 | RFC 1918 private |
192.168.0.0/16 | RFC 1918 private |
127.0.0.0/8 | Loopback |
::1/128 | IPv6 loopback |
169.254.0.0/16 | Link-local / AWS / GCP / Azure IMDS |
fd00::/8 | IPv6 ULA |
100.64.0.0/10 | Carrier-grade NAT |
*.internal, metadata.google.internal | Cloud-provider metadata FQDNs |
SafeUrl is a distinct Rust type. No HTTP call is made without first
constructing a SafeUrl — building one panics at compile time when
bypassed, and returns an error at runtime on blocked addresses.
Cannot be disabled — the SSRF guard is compiled unconditionally.
Layer 3 — Command Scanner (command_scan.rs)
Section titled “Layer 3 — Command Scanner (command_scan.rs)”Before any shell command executes via the terminal tool, the
CommandScanner runs two passes over the normalized command string
(ANSI-stripped, NFKC-normalized, lowercased):
Pass 1 — Aho-Corasick O(n) literal scan
38 literal patterns across 8 danger categories:
| Category | Example patterns |
|---|---|
DestructiveFileOps | rm -r, rm -f, rmdir, shred, find -delete, dd if=, -exec rm |
PermissionEscalation | chmod 777, chown -R root |
SystemDamage | mkfs, > /dev/sd, > /etc/, systemctl stop, `:(){ |
SqlDestruction | drop table, drop database, truncate table |
RemoteCodeExecution | ` |
ProcessKilling | kill -9 -1, pkill -9 |
GatewayProtection | gateway run &, nohup ... gateway |
FileOverwrite | tee /etc/, tee .ssh/ |
Pass 2 — Regex scan for non-contiguous patterns
Patterns that require lookahead or non-adjacent keywords:
DELETE FROMwithout aWHEREclause (SQL)find PATH -exec rm(non-adjacent)bash <(curl ...)/sh < <(wget ...)(process substitution)bash -lc,sh -ic(combined -c flag forms)- Gateway run outside systemd (
nohup ... disown)
Tool-generated commands containing flagged patterns are blocked and the LLM receives a rejection message. User-typed commands in the TUI are not scanned — the user is trusted.
Layer 4 — Output Redaction (redact.rs)
Section titled “Layer 4 — Output Redaction (redact.rs)”All LLM text — before display and before logging — passes through the
redaction pipeline. Matched patterns are replaced with [REDACTED]:
| Pattern | Matches |
|---|---|
sk-[A-Za-z0-9]{20,} | OpenAI API keys |
ghp_[A-Za-z0-9]{36} | GitHub personal access tokens |
github_pat_[A-Za-z0-9_]{80,} | Fine-grained GitHub PATs |
AKIA[A-Z0-9]{16} | AWS access key IDs |
-----BEGIN .* PRIVATE KEY----- | PEM private keys |
| High-entropy strings > 40 chars | Generic secrets (base64-like) |
The raw API response is never written to disk. The SQLite session database stores only the redacted form.
Layer 5 — Prompt Injection Detection (injection.rs)
Section titled “Layer 5 — Prompt Injection Detection (injection.rs)”Tool results (file contents, web pages, process output) are scanned for prompt-injection markers before being injected into the LLM context:
Ignore (all|previous|above) instructionsYou are now/Act asoverride attempts- Hidden Unicode direction overrides (BiDi)
<|im_start|>/<|system|>token injections
Detected injections are:
- Flagged with a warning banner in the TUI
- Wrapped in a sandbox comment so the LLM knows the content is untrusted user data, not system instructions
Layer 6 — Approval Policy (approval.rs)
Section titled “Layer 6 — Approval Policy (approval.rs)”Destructive operations can require explicit user approval before execution. Three modes:
| Mode | Behavior |
|---|---|
off | No approval required (default in interactive TUI) |
smart | Approve when risk score exceeds threshold |
manual | All tool calls require /approve or inline button |
In gateway platforms (Telegram, Discord), approval appears as inline
buttons. In the TUI, /approve and /deny slash commands confirm or
reject pending actions.
Layer 7 — Code Sandbox Isolation (execute_code)
Section titled “Layer 7 — Code Sandbox Isolation (execute_code)”The execute_code tool runs user-supplied Python, JavaScript, Bash, Ruby, Perl, or Rust
scripts inside an isolated subprocess. Two protections apply before the subprocess starts:
API key stripping: All ANTHROPIC_API_KEY, OPENAI_API_KEY, and other known credential env vars are removed from the subprocess environment. Scripts cannot exfiltrate your API keys by reading environment variables.
7-tool RPC over Unix socket: The sandbox can only interact with the outside world through exactly 7 whitelisted tool RPCs via a Unix domain socket (/tmp/edgecrab-sandbox-*.sock). It cannot make arbitrary HTTP calls or execute shell commands outside the RPC surface.
Timeout + output cap: Maximum 5 minutes of execution; stdout is capped at 50 KB.
This layer lives in crates/edgecrab-tools/src/tools/execute_code.rs, not in edgecrab-security, but is a compiled-in constraint applied at every execute_code invocation.
State Integrity
Section titled “State Integrity”The SQLite session database uses WAL (Write-Ahead Logging) mode:
- Concurrent reads never block writes
- Crash-safe: power failure mid-write cannot corrupt the database
- Integrity verified on startup via
PRAGMA integrity_check
Principle of Least Privilege — Config Template
Section titled “Principle of Least Privilege — Config Template”tools: file: allowed_roots: - /path/to/your/project # never broader than needed terminal: timeout_seconds: 10 # short timeout = smaller blast radius allowed_commands: # optional allowlist - cargo - git - grep web: max_results: 5
security: path_restrictions: [] # optional deny-list inside the workspace/allowed roots ssrf_guard: true # cannot be false — compile-time guard command_scan: true output_redaction: true approval_required: [] # add destructive command patterns hereReporting Security Issues
Section titled “Reporting Security Issues”Report vulnerabilities privately via GitHub Security Advisories. Do not open a public issue for security bugs.
Security in Practice: Common Scenarios
Section titled “Security in Practice: Common Scenarios”Scenario 1: Constraining a refactoring task
# Only allow reading and writing inside the projecttools: file: allowed_roots: - /home/you/projectIf the agent tries to read /etc/hosts or any file outside the workspace plus allowed_roots, the call is blocked by the shared path policy.
Scenario 2: Review before any shell command
security: approval_required: - "rm" - "git push"Matching terminal commands require approval before running. Non-matching commands follow the normal terminal policy.
Scenario 3: Block all network access
tools: enabled_toolsets: - file - terminal - memoryNo web/browser toolsets → no HTTP calls from agent tools. The SSRF guard still protects terminal commands that happen to make HTTP requests.
Scenario 4: Team deployment — lock down messaging
gateway: telegram: allowed_users: - alice - bob home_channel: "-100123456789" slack: allowed_users: - U012ABCDE - U098FGHIJOnly explicitly listed users can interact with the agent. All others receive an “access denied” response.
Pro Tips
Section titled “Pro Tips”Prefer allowed_roots over relying on agent judgment. The agent is smart, but the path policy is deterministic runtime enforcement. Always set the smallest roots you actually need.
Run edgecrab doctor after changing security config. It checks that your settings are valid before you rely on them.
Log everything in production. Set save_trajectories: true in config.yaml. All tool calls and results are saved as JSON trajectory files in ~/.edgecrab/trajectories/. Invaluable for post-incident review.
Frequently Asked Questions
Section titled “Frequently Asked Questions”Q: Can the agent read my SSH keys or credentials?
Not if the workspace root and allowed_roots exclude them. By default, file tools can read only inside the active workspace. To keep credentials inaccessible even inside a broad workspace, also add security.path_restrictions entries for sensitive subtrees.
tools: file: allowed_roots: - /home/you/your-projectQ: Can a malicious web page take control of the agent?
EdgeCrab implements prompt injection detection (Layer 5). Content containing common injection markers is wrapped in a sandbox comment and flagged. This is defense-in-depth — do not rely on it as the only control. Never point the agent at untrusted web pages without an explicit approval policy.
Q: Can the SSRF guard be disabled?
No. It’s compiled unconditionally. SafeUrl is a Rust type — constructing an HTTP request without first constructing a SafeUrl is a compile error. Runtime configuration can’t disable this.
Q: What happens if a command scanner match is a false positive?
User-typed commands in the TUI are never scanned — only agent-generated commands. If the agent is blocked from a legitimate command:
- Type the command yourself in the TUI instead
- Or temporarily add it to
terminal.allowed_commands
Q: Does EdgeCrab send any data to external servers by default?
Only to the configured LLM API. No telemetry, no crash reporting, no analytics. Network calls are limited to: LLM provider API, web tools (if enabled), gateway platforms (if configured), and Honcho (if cloud sync is enabled).
v0.6 Security Enhancements
Section titled “v0.6 Security Enhancements”Hardened SSRF HTTP Client
Section titled “Hardened SSRF HTTP Client”Web tools now use a shared SSRF-guarded HTTP client (edgecrab_security::ssrf::build_ssrf_client()) that enforces:
- DNS resolution checks before every request
- Redirect following disabled (prevents open-redirect SSRF)
- Connection timeout enforcement
- Consistent configuration across all web tool endpoints
HTTP Proxy Support
Section titled “HTTP Proxy Support”Outbound requests respect HTTPS_PROXY and HTTP_PROXY environment variables. The proxy configuration is applied at the edgecrab-security crate level, ensuring all HTTP clients (web tools, gateway adapters) route through the configured proxy.
Gateway Webhook Validation
Section titled “Gateway Webhook Validation”- Twilio SMS: Incoming webhooks are validated using Twilio’s
X-Twilio-SignatureHMAC-SHA1 verification - WeChat/Weixin: Messages use AES-256-CBC XML encryption for secure transport
Skills Guard
Section titled “Skills Guard”External skills installed via /skills install pass through a 23-pattern security scanner before installation. Patterns cover exfiltration, prompt injection, destructive operations, persistence mechanisms, and obfuscation techniques.
See Also
Section titled “See Also”- Configuration — Full
security.*config reference - Docker Deployment — Additional container security
- Architecture — How security crates are structured in the codebase