> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useanima.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Security

> Learn about Anima security controls, dual-layer scanning, policy engine rules, and operational best practices.

# Security

Built-in safeguards to protect your agents, users, and outbound communications.

### API Keys

Two types: Master Keys (full admin access) and Agent Keys (scoped to a single mailbox).

### Dual-Layer Content Scanning

Scans with both deterministic regex heuristics and AI classification.

## API Key Types

| Type       | Prefix | Permissions                                            | Best Practice                                                      |
| ---------- | ------ | ------------------------------------------------------ | ------------------------------------------------------------------ |
| Master Key | `mk_`  | Full access. Create agents, manage billing, view logs. | Store in server-only environment variables and rotate on schedule. |
| Agent Key  | `ak_`  | Scoped access. Send/receive for one specific agent.    | Issue least-privilege keys per service and revoke unused keys.     |

## Content Scanning Overview (Regex + AI)

* **Regex Layer:** Fast checks for known injection markers, secret patterns, and risky payload signatures.
* **AI Layer:** GPT-4o-mini classification into `SAFE`, `SUSPICIOUS`, or `BLOCKED`.
* **Fallback Safety:** If AI credentials are missing, scanning gracefully continues in regex-only mode.

> **Note:** Use `low`, `medium` (default), or `high` sensitivity depending on risk tolerance and expected message variability.

## Content Policy Configuration

The policy engine applies layered rules to outbound content and can combine deterministic and model-based checks.

* **Regex rules:** Match known dangerous patterns.
* **AI rules:** Enforce decisions based on model classification.
* **Domain rules:** Whitelist or blacklist domains in message content.
* **Keyword rules:** Detect finance, attachment, and social engineering signals.

```ts theme={null}
const policies = [
  {
    id: "block-injection",
    name: "Block Injection",
    action: "block",
    priority: 100,
    rules: [
      { type: "regex", value: "ignore\\s+previous\\s+instructions", description: "Prompt injection" },
      { type: "ai", value: ["BLOCKED"], description: "AI high-risk verdict" }
    ]
  }
];
```

## Agent Capability Policies

Separate from content scanning: each agent carries an optional **capability policy** — hard limits an org admin sets on what the agent may do, regardless of message content.

Read it with `GET /v1/agents/{agentId}/policy` (any key in the org). Write it with `PUT /v1/agents/{agentId}/policy` (master key only):

```bash theme={null}
curl -X PUT https://api.useanima.sh/v1/agents/agt_.../policy \
  -H "Authorization: Bearer mk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "policy": {
      "email": {
        "allowedRecipientDomains": ["example.com"],
        "blockedRecipientDomains": [],
        "maxPerHour": 20
      },
      "vault": { "readOnly": true, "blocked": false },
      "phone": { "allowedCountries": ["US", "DE"], "maxSmsPerHour": 10, "blocked": false }
    }
  }'
```

| Field                           | Type       | Meaning                                                                               |
| ------------------------------- | ---------- | ------------------------------------------------------------------------------------- |
| `email.allowedRecipientDomains` | `string[]` | If non-empty, the agent may **only** send to these domains. Empty = no restriction.   |
| `email.blockedRecipientDomains` | `string[]` | The agent may **never** send to these domains.                                        |
| `email.maxPerHour`              | `number`   | Per-agent override of the emails-per-hour rate limit.                                 |
| `vault.readOnly`                | `boolean`  | Agent can read vault items but not create, update, or delete them.                    |
| `vault.blocked`                 | `boolean`  | Disable vault access for this agent entirely.                                         |
| `phone.allowedCountries`        | `string[]` | ISO 3166-1 alpha-2 codes. If non-empty, the agent may only call/text these countries. |
| `phone.maxSmsPerHour`           | `number`   | Per-agent override of the SMS-per-hour rate limit.                                    |
| `phone.blocked`                 | `boolean`  | Disable phone/SMS for this agent entirely.                                            |

Every section is optional — omit one to leave that channel unrestricted. Validation is strict: unknown fields are rejected with a `400` rather than silently ignored, so typos can't create a policy that looks stricter than it is.

An email send that violates the policy is refused and logged as a security event, so blocked attempts show up in the audit trail.

> **Note:** Email constraints are enforced on every send today. Vault and phone constraints are validated and stored, but not yet enforced at request time.

## Rate Limiting for AI Scanning

AI scanning is rate limited to 100 req/min, uses an LRU cache with 1000 entries and a 5min TTL, and falls back to regex scanning when needed.

## Attachment Scanning

Email attachments are scanned both when an agent receives them and before an agent sends them, so malicious files are caught in either direction.

* **Magic-byte detection:** the actual leading bytes are inspected, not the declared type or the file extension (both are trivially spoofed). An executable or script disguised as `invoice.pdf` is unmasked and blocked.
* **Content scanning:** text attachments run through the same content scanner as message bodies, catching leaked credentials, PII, and risky file types.
* **Verdict:** each attachment gets a `scanStatus` of `CLEAN`, `FLAGGED`, or `BLOCKED`, surfaced in the message's attachment metadata so an agent can decide before fetching the bytes.

A `BLOCKED` attachment cannot be downloaded — the download endpoint returns `403`. Download URLs are short-lived (15 minutes) and scoped to the requesting agent.

## Webhook Security (HMAC Verification)

Webhook payloads are protected with HMAC verification and freshness checks to prevent tampering and replay attacks.

* Use a dedicated webhook secret.
* Verify the HMAC signature on every request.
* Compare signatures using constant-time comparison.
* Reject requests that fail timestamp freshness checks.

> **Warning:** If content is blocked by policy, the API returns a denial response with a reason code so you can audit and tune policy behavior safely.

## Operational Best Practices

* Rotate keys on a regular schedule.
* Store master keys only in server-side environments.
* Use least-privilege agent keys per service.
* Review blocked events and adjust policies carefully.
