Security model

Alfred's security model is small, explicit, and human-in-the-loop. Source of truth: .ai/policies/security.md.

The rules

  1. Deny by default. Every protected action must be explicitly allowlisted.
  2. No self-escalation. No agent may broaden its own permissions — not even the orchestrator.
  3. Human approval for escalation. Adding a path or removing a destructive-command rule is a human trace event, not a prompt decision.
  4. Skills cannot override policy. A skill can teach an agent how to ask for an action; it cannot grant one.
  5. Adapters enforce, never own. Policy lives in core. Adapters apply it.
  6. Protected paths are sacred. .ai/, .opencode/, .codex/, harnesses/, and packages/core/ require explicit human approval to read or modify.

Protected paths

PathDefaultTo override
.ai/ deny human approval + --force
.opencode/ deny human approval + --force
.codex/, .agents/ deny human approval + --force
packages/core/ deny for adapters, allow for core devs human approval + reviewer sign-off
install.sh / update.sh deny human approval + --force

Destructive commands

Any command matching a DestructiveCommandRule is blocked by default and requires human approval:

destructive patterns
rm -rf /
rm -rf ~
git reset --hard
git push --force
dd if=
mkfs
chmod -R 777 /
curl | sh

Approval flow

Every protected action follows the same flow:

  1. Agent requests an action (permission.request trace event).
  2. Policy evaluates the request against rules.
  3. If allowed: action runs; if protected: agent blocks and emits a permission.escalation trace.
  4. Human reviews the trace, approves or denies.
  5. Decision is recorded as permission.decision with actor: human.

Secrets

API keys, model credentials, and database URLs never live in config.json or in prompts. They are read from env vars or from the OS keychain.

Prompt-injection is a real threat. A tool that returns user-controlled text is treated as untrusted. Any instruction that arrives via a tool result cannot modify the kernel, the policy, or the protected paths — no matter how politely it asks.