---
title: Security Model
description: How earl protects secrets, enforces policies, and blocks attacks
icon: Shield
---

Earl's security model has four layers: template-driven access control, keychain-backed secrets, network egress rules, and SSRF protection. Each layer is independent — they compose for defense in depth.

## Template-Driven Access

Agents never make raw HTTP requests. Every API call must match a pre-defined HCL template:

```bash
# This works — matches a template
earl call 'github.search_issues(query="is:issue", per_page=5)'

# Arbitrary URLs are impossible — there's no "raw request" command
```

Templates are reviewed ahead of time. Each one declares:
- The exact URL pattern and HTTP method
- Required parameters with types
- Which secrets it can access (`annotations.secrets`)
- Whether it's read-only or write (`annotations.mode`)

Write-mode commands require explicit `--yes` approval at the CLI or MCP server level.

## Keychain-Backed Secrets

Secret values are stored in the **OS keychain** (macOS Keychain, Linux Secret Service, Windows Credential Manager) — never on disk in plaintext.

- `earl secrets set` stores values in the keychain.
- `earl secrets get` returns **metadata only** — never the plaintext value.
- Templates reference secrets by key (e.g., `secrets.github.token`) during request rendering.
- Output templates (`result.output`) **cannot** access `secrets.*`.

An agent using earl cannot read your secrets, even with full shell access to the `earl` binary.

## Network Egress Rules

Without configuration, earl allows outbound requests to any destination. Add `[[network.allow]]` rules to restrict egress to specific hosts:

```toml
[[network.allow]]
scheme = "https"
host = "api.github.com"
port = 443
path_prefix = "/"
```

When any `[[network.allow]]` entry is present, **all** outbound requests must match at least one rule. Requests to unlisted hosts are blocked.

For CLI-protocol templates, commands must be listed in `network.allow_cli_commands`:

```toml
[network]
allow_cli_commands = ["cargo", "git"]
```

## SSRF Protection

Earl blocks requests to private and reserved IP ranges to prevent Server-Side Request Forgery attacks. This is enforced **after** DNS resolution, so a template pointing to a public hostname that resolves to a private IP is still blocked.

Blocked ranges include:
- `127.0.0.0/8` (loopback)
- `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` (RFC 1918)
- `169.254.0.0/16` (link-local)
- `::1`, `fc00::/7`, `fe80::/10` (IPv6 equivalents)

## Secret Redaction

If a secret value appears in command output (e.g., an API accidentally echoes a token), earl's redactor replaces it with `[REDACTED]` before displaying the result.

## File Permissions

The security model assumes agents **cannot modify** earl's configuration or template files. If an agent can edit `config.toml`, it can add permissive network rules. If it can edit templates, it can exfiltrate secrets.

Lock down file permissions after setup:

```bash
# Protect config directory
chmod 700 ~/.config/earl
chmod 600 ~/.config/earl/config.toml
chmod -R go-w ~/.config/earl/templates

# Protect workspace templates
chmod -R 700 ./templates/
```

For stronger isolation, run the AI agent as a separate, less-privileged user that can execute `earl` but cannot modify its configuration files.
