Security Model
Current posture in one sentence: the platform trusts its network completely — there is no authentication, no authorization, and no rate limiting — which is acceptable for local development and nothing else.
Anyone who can reach port 8001 can create agents, read every conversation, upload documents, trigger paid OpenAI calls, and delete data. Deployment guidance in Deployment assumes a private network until the hardening items below land.
What exists today
| Control | Status | Where |
|---|---|---|
| Secret management | ✅ OPENAI_API_KEY read from .env (gitignored), never logged, never returned by any endpoint | services/*.py |
| Server-side LLM calls only | ✅ The browser never holds the OpenAI key; all calls originate in the backend | whole design |
| Tool authorization per agent | ✅ enabled_tools allow-list checked before any tool runs (403 otherwise) | agent_has_tool() in both routers |
| Tenant isolation for vectors | ✅ Every Chroma query filters where={"agent_id": ...} | document_service.search_agent_documents |
| Input validation | ✅ Pydantic schemas on every body; upload restricted to UTF-8 .txt | schemas.py, documents.py |
| SQL injection resistance | ✅ All queries go through the SQLAlchemy ORM (parameterized) | models.py usage |
| Destructive-action guard | ⚠️ Partial — task status changes validated against an allow-list; the (buggy) delete path requires ?force=true when data exists | routers/agents.py |
| User authentication | ❌ None — no users, sessions, tokens, or API keys | — |
| Authorization / roles | ❌ None — every caller can do everything | — |
| Rate limiting / quotas | ❌ None — unbounded paid OpenAI spend per caller | — |
| CORS policy | ❌ Not configured (no CORSMiddleware) — browsers cannot call the API cross-origin, which the frontend sidesteps via server-side fetching | — |
| HTTPS / TLS | ❌ Local HTTP only | — |
| Audit trail | ⚠️ Operational logging exists (ToolCall/runs) but records no actor identity | — |
Trust boundaries
The only real boundary today is outbound: the OpenAI key stays server-side, and prompts sent to OpenAI are subject to OpenAI's data-usage policies — treat uploaded documents and emails accordingly.
Prompt-injection surface
LLM inputs are user-controlled (email_text, chat messages, uploaded documents). Mitigations currently in place are structural rather than filtering:
- The email analyzer, evaluator, and reviewer demand strict JSON output and the backend validates it with
json.loads, raising on garbage — a malicious email can skew content but cannot change shape. - The RAG answer prompt instructs the model to use only the provided context and to refuse otherwise; the corrective evaluator independently gates generation (Corrective RAG).
- Task creation from action items is bounded: only
title,priority,deadlinefields flow intoTaskrows, andnormalize_due_datesanitizes dates.
There is no content filtering or output moderation; a hostile email can still produce a hostile suggested reply. The Reviewer Agent (approved, issues) is the current line of defense — treat its verdict as advisory, not enforcement.
Hardening checklist for production
Priority-ordered; tracked on the Roadmap:
- Authentication — API keys or OAuth2/JWT via FastAPI dependencies; scope every
/agents/{id}/*route to the caller's tenant. - Authorization — ownership checks (which user owns which agent) on top of the existing tool gating.
- Rate limiting & spend caps — per-caller request limits and a daily OpenAI budget circuit breaker (the
estimated_costdata already exists to build on). - CORS middleware — explicit allowed origins if the browser ever calls the API directly.
- TLS termination — reverse proxy (Caddy/Nginx) or platform TLS.
- Secrets manager — move
.envto platform secret storage in deployment. - Upload limits — max file size on
/documents/upload(currently unbounded). - Structured audit logging — attach actor identity to
ToolCall/AgentRunrows.
Related pages
- Configuration — secret handling in development
- Error Handling — what leaks in error messages (exception strings are returned in
detail) - Roadmap — when hardening is planned