# Security

Tracks the must-haves in `LEGATE_AGENT_BUILD_PLAN.md` Section 14. Items are
marked as they land.

| Requirement | Status | Notes |
|---|---|---|
| JWT access + refresh, short access TTL, rotation on refresh | ✅ | `legate/security/tokens.py` |
| Argon2 / bcrypt password hashing | ✅ | Argon2id via `argon2-cffi` |
| API keys stored hashed | ✅ | Keyed HMAC-SHA256 peppered with the server secret; only the digest and a short prefix are stored, plaintext shown once (`legate/security/api_keys.py`) |
| Credential vault: envelope encryption, rotation | ✅ | `legate/vault/crypto.py` — per-record DEK wrapped by a versioned master key; secrets never returned |
| Treat ingested/connector content as untrusted | 🟡 | Tool output (incl. `kb.search` retrieved passages) wrapped as untrusted data in the agent loop (`runner.py`); per-workspace KB collection isolation enforced |
| Default-deny tools; sensitive tools gated by policy + approval | ✅ | Policy Engine default-denies non-allow-listed tools; sensitive tools require human approval via the inbox (`legate/api/approvals.py`), with per-workspace auto-approve/deny rules |
| Every policy decision audited | ✅ | `policy.deny` / `policy.require_approval` / `policy.auto_approve` and `approval.approve` / `approval.reject` all written to the hash-chained log |
| Webhook HMAC verification | ✅ | `legate/workflow/webhooks.py` — per-workflow secret, constant-time compare; invalid signatures rejected with 401 |
| Safe templating (no code execution) | ✅ | `legate/workflow/templating.py` — AST walker allows only literals/comparisons/boolean ops; no calls/attributes/names |
| Parameterized DB queries only | ✅ | SQLAlchemy ORM; no string SQL |
| Rate limiting + per-workspace quotas | ✅ | `legate/security/ratelimit.py` + plan run quotas (`legate/billing`); gated by `RATE_LIMIT_ENABLED` / `BILLING_ENABLED` |
| Immutable, hash-chained audit log | ✅ | `legate/audit/service.py` |
| SSRF protection on outbound connector / MCP URLs | ✅ | `legate/security/ssrf.py` — resolves and blocks private, loopback, and link-local targets; opt back in with `ALLOW_PRIVATE_CONNECTOR_URLS` |
| Dependency + secret scanning, CodeQL | ✅ | `.github/workflows/ci.yml` |

## RBAC matrix

Implemented in `legate/policy/rbac.py` and verified cell-by-cell in
`tests/test_rbac.py`. Roles: Owner, Admin, Builder, Operator, Viewer.
