Skip to content

Security

Hoard implements multiple security layers to protect your data while enabling AI agent access.

Security Layers

┌─────────────────────────────────────────┐
│ MCP Request │
└─────────────────┬───────────────────────┘
┌─────────────────────────────────────────┐
│ 1. Token Authentication │
│ • Verify Bearer token present │
│ • Token must exist in config │
└─────────────────┬───────────────────────┘
┌─────────────────────────────────────────┐
│ 2. Scope Checking │
│ • Token has required scope │
│ • Tool matches allowed scopes │
└─────────────────┬───────────────────────┘
┌─────────────────────────────────────────┐
│ 3. Rate Limiting │
│ • Per-token limits │
│ • Per-tool limits │
│ • Byte/chunk caps │
└─────────────────┬───────────────────────┘
┌─────────────────────────────────────────┐
│ 4. Sensitivity Filtering │
│ • Check entity sensitivity │
│ • Require 'sensitive' scope │
└─────────────────┬───────────────────────┘
┌─────────────────────────────────────────┐
│ 5. Audit Logging │
│ • Log all tool calls │
│ • Track access patterns │
└─────────────────────────────────────────┘

Token Scopes

Tokens define what actions are permitted:

security:
tokens:
- name: "claude-code"
scopes: ["search", "get", "memory.read"]
- name: "admin"
scopes: ["search", "get", "memory", "sensitive", "sync", "ingest"]
ScopeAllows
searchsearch() tool
data.searchAlias for search
getget(), get_chunk()
data.getAlias for get
memoryMemory read and write (legacy scope)
memory.readmemory_get, memory_search
memory.writememory_put and other memory write tools
ingestinbox_put
syncsync, sync_status, sync_run, embeddings_build
agent.registerRegister agents (Orchestrator)
agent.selfManage own agent state (Orchestrator)
agent.readList agents (Orchestrator)
task.createCreate tasks (Orchestrator)
task.claimPoll and claim tasks (Orchestrator)
task.executeStart/complete/fail tasks (Orchestrator)
task.manageCancel tasks (Orchestrator)
task.readRead task details (Orchestrator)
artifact.readRead artifacts (Orchestrator)
artifact.writeWrite artifacts (Orchestrator)
event.readPoll events (Orchestrator)
event.writePublish events (Orchestrator)
cost.readCost summary and budgets (Orchestrator)
cost.writeCost reporting (Orchestrator)
workflow.createCreate workflows (Orchestrator)
workflow.manageStart/pause/resume/cancel workflows (Orchestrator)
workflow.readRead workflow status and definitions (Orchestrator)
sensitiveAccess entities with sensitivity='sensitive' or 'secret'

Orchestrator Tokens

  • HOARD_SERVER_SECRET is required to start the write-enabled server and can act as an admin token.
  • HOARD_REGISTRATION_TOKEN is required for agent.register when onboarding new agents.

Rate Limiting

Prevents runaway agents from exhausting resources:

rate_limits:
search_requests_per_minute: 30
get_requests_per_minute: 60
chunks_returned_per_hour: 5000
bytes_returned_per_hour: 50000000 # 50MB

Per-Tool Limits

ToolRate Limit KeyDefault
searchsearch_requests_per_minute30/min
getget_requests_per_minute60/min
get_chunkget_requests_per_minute60/min
memory_getget_requests_per_minute60/min
memory_putget_requests_per_minute60/min
memory_searchget_requests_per_minute60/min
syncget_requests_per_minute60/min
sync_statusget_requests_per_minute60/min
sync_runget_requests_per_minute60/min
inbox_putget_requests_per_minute60/min
embeddings_buildget_requests_per_minute60/min

Byte/Chunk Caps

Hourly caps prevent bulk exfiltration:

  • 5,000 chunks/hour — Limits enumeration
  • 50MB/hour — Limits large document scraping

Sensitivity Levels

Entities can have sensitivity levels:

LevelMCP AccessSet By
normalAll tokens with get scopeConnectors, CLI
sensitiveOnly tokens with sensitive scopeConnectors, CLI
secretOnly tokens with sensitive scopeConnectors, CLI

Setting Sensitivity

Set sensitivity via connectors when indexing:

EntityInput(
source="my_source",
source_id="id",
sensitivity="sensitive",
...
)

Anti-Exfiltration Measures

Hoard prevents bulk data extraction:

ProtectionHow It Works
No export_allTool doesn’t exist
No list_allCan’t enumerate entities
Rate limitsCaps requests over time
Byte capsLimits total data returned
Audit logsDetects suspicious patterns

Audit Logging

All MCP requests are logged to the SQLite database (audit_logs table). Each log entry includes:

  • Token name
  • Tool called
  • Success/failure status
  • Chunks and bytes returned
  • Timestamp

View audit logs by querying the database:

Terminal window
sqlite3 ~/.hoard/hoard.db "SELECT * FROM audit_logs ORDER BY request_at DESC LIMIT 10"

Connector Security (v1)

Aspectv1 Reality
Permissions in manifestInformational only, not enforced
Network accessConnectors can make any request
File accessConnectors can read any file
ExecutionSame process as Hoard core

Mitigations:

  • Connectors reviewed before recommendation
  • Provenance tracking shows which connector indexed what
  • Users install connectors explicitly

Future: v2 will add OS-level sandboxing.

Token Management

Create Token

Terminal window
hoard tokens add my-token --scopes search,get,memory.read,ingest

List Tokens

Terminal window
hoard tokens list

Remove Token

Terminal window
hoard tokens remove my-token

Best Practices

  1. Minimal scopes — Only grant what’s needed
  2. Separate tokens — One per AI tool
  3. Review audit logs — Check for anomalies
  4. Keep Hoard updated — Security fixes ship regularly

Configuration

Full security configuration:

security:
tokens:
- name: "claude-code"
token: "hoard_sk_..."
scopes: ["search", "get", "memory.read"]
- name: "admin"
token: "hoard_sk_..."
scopes: ["search", "get", "memory", "sensitive", "sync", "ingest"]
rate_limits:
search_requests_per_minute: 30
get_requests_per_minute: 60
chunks_returned_per_hour: 5000
bytes_returned_per_hour: 50000000

Next Steps