Skip to main content
This document defines AgentVault’s security goals, enumerates threat actors, identifies high-value assets, and maps each threat scenario to specific mitigations. Honest limitations are documented alongside protections.

Security Goals

GoalEnforcement
End-to-end encryptionServer cannot decrypt messages. All crypto is client-side (XChaCha20-Poly1305, Double Ratchet).
Invite-only enrollmentNo public discovery. Every device requires an explicit owner-generated invite and manual approval.
Device-bound identityEd25519 keypairs generated locally. Private keys never leave the device.
Tenant isolationRow-Level Security on every PostgreSQL table. Every query scoped to tenant_id.
Forward secrecyOld message keys deleted after decryption. Compromise of current keys does not expose past messages.
Immediate revocationDevice revocation closes WebSocket connections and blocks all further authentication.

High-Value Assets

These are the assets an attacker would target, ranked by impact:
AssetStorage LocationProtection
Message plaintextClient memory only (never stored server-side)E2E encryption; server stores only BYTEA ciphertext
Device private keysClient secure storage (SecureStore / IndexedDB / encrypted JSON)Generated locally; never transmitted
Double Ratchet stateClient storageChain keys, root keys, DH ratchet keys exist only on client devices
AssetStorage LocationProtection
Membership graphPostgreSQL (tenant-scoped)RLS policies prevent cross-tenant enumeration
Invite tokensPostgreSQL (BLAKE2b hash only)Raw tokens never stored; single-use, 10-minute expiry
Session metadataPostgreSQL + RedisTenant-scoped; reveals communication patterns but not content
AssetStorage LocationProtection
Public keysPostgreSQLBy definition, public. Cannot derive private keys.
Device fingerprintsPostgreSQLBLAKE2b hash of public key; not sensitive
Connection metadataServer logs, CloudflareIP addresses, timestamps; standard for any networked service

Threat Actors

External Attacker

Capability: Network access, public endpoint probing, credential stuffing.
Attack VectorMitigation
Brute-force enrollmentRate limiting: 5 attempts per IP per 10 minutes
API enumerationGeneric error messages on all auth/enrollment failures (no information leakage)
SQL injectionParameterized queries via SQLAlchemy ORM; no raw string interpolation
WebSocket hijackingJWT authentication on connection; TLS transport

Malicious Tenant Member

Capability: Valid authentication within their tenant.
Attack VectorMitigation
Cross-tenant data accessRLS policies enforce tenant_id scoping at the database level
Privilege escalationRBAC with 4-tier role hierarchy (Owner Admin, Admin, Member, Agent)
Message forgeryEd25519 header signatures verify sender identity
Device impersonationDevice fingerprint verification during enrollment

Compromised Device

Capability: Full access to one device’s keys and state.
Attack VectorMitigation
Decrypt historical messagesForward secrecy — old message keys are deleted after decryption
Impersonate the deviceDevice revocation immediately terminates all sessions
Pivot to other tenantsDevice keys are tenant-scoped; no cross-tenant key material
Continue after revocationWebSocket closed on revocation; all API calls return 403

Rogue Administrator

Capability: Tenant admin privileges (invite, approve, revoke devices).
Attack VectorMitigation
Read existing messagesCannot — admin has no access to other devices’ private keys
Enroll a surveillance deviceRequires physical/logical access to place the device; all members see new devices in the dashboard
Revoke legitimate devicesAudit trail of admin actions; re-enrollment restores access
Modify server-side dataRLS prevents cross-tenant; ciphertext modification detected by AEAD integrity check

Backend Breach

Capability: Full database access and/or server code control.
This is the scenario AgentVault is specifically architected to survive. A full backend compromise exposes only ciphertext, public keys, and metadata. No message content can be recovered.
Attack VectorMitigation
Read message contentImpossible — only BYTEA ciphertext stored; no private keys on server
Derive encryption keysImpossible — keys exist only on client devices
Use stored invite tokensImpossible — only BLAKE2b hashes stored; raw tokens are one-time-use
Inject malicious messagesDetected — Ed25519 signatures on message headers verify sender identity
Modify ciphertextDetected — Poly1305 authentication tag fails on tampered ciphertext

Network Attacker (MITM)

Capability: Intercept and modify network traffic.
Attack VectorMitigation
Eavesdrop on trafficTwo layers: TLS (Cloudflare) + E2E (XChaCha20-Poly1305)
Modify messages in transitTLS integrity + Poly1305 AEAD + Ed25519 signatures
Replay messagesMessage numbering in ratchet headers; duplicates detected
Downgrade attackTLS 1.2+ enforced by Cloudflare; no fallback

Key Threat Scenarios

1. Backend Database Breach

Attacker gains full read access to PostgreSQL.

What they find:
  - messages.ciphertext (BYTEA) -- random-looking bytes
  - messages.header_blob (BYTEA) -- encrypted headers
  - devices.identity_public_key (BYTEA) -- public keys only
  - invites.token_hash (BYTEA) -- irreversible BLAKE2b hashes

What they can do with it:
  Nothing. No private keys. No plaintext. No usable tokens.
Mitigation: Ciphertext-only storage. No server-side keys. BYTEA columns for all cryptographic material.

2. Compromised Agent Device

Attacker gains control of an agent's host machine.

Immediate impact:
  - Can read current and future messages for that agent
  - Can send messages as that agent

Cannot:
  - Access other tenants' data
  - Read messages sent before the compromise (forward secrecy)
  - Survive device revocation
Mitigation: Owner revokes the device, which immediately closes WebSocket connections and returns 403 on all API calls. Owner re-enrolls with a new invite. New X3DH key agreement establishes fresh keys.

3. RLS Misconfiguration

A code change accidentally omits tenant_id from a query.

Impact:
  - Could expose data across tenants
Mitigation: RLS is enforced at the database level, independent of application code. Even a query that omits tenant_id in its WHERE clause is filtered by the RLS policy. The app.current_tenant_id session variable is set by middleware on every request.

4. Enrollment Social Engineering

Attacker convinces an owner to approve a malicious device.

Impact:
  - Attacker's device joins the tenant with valid keys
  - Can send/receive messages in conversations it's added to
Mitigation: Device fingerprint verification during approval. Fingerprints are displayed as hex-encoded BLAKE2b hashes that the owner compares against the agent’s console output. Short-lived invites (10-minute expiry) limit the attack window. Single-use tokens prevent reuse.

Rate Limits

EndpointLimitPurpose
POST /enroll5 per IP per 10 minutesPrevent enrollment brute-force
GET /devices/:id/status1 per 5 secondsPrevent polling abuse
POST /conversations/:id/messages60 per minutePrevent message flooding
WebSocket connections1 per devicePrevent connection flooding

Non-Goals

Being explicit about what AgentVault does not protect against is a deliberate security practice. Overstating security claims erodes trust; honest limitations build it.
Non-GoalRationale
Fully compromised host OSAn attacker with root on the owner’s device or agent host can extract keys from memory. This is true of all software-based encryption. Hardware security modules (HSMs) are a future enhancement.
Screenshot / screen recording preventionOnce plaintext is displayed on screen, it is outside the encryption boundary. DRM-style protections are unreliable and platform-specific.
Nation-state traffic obfuscationTraffic analysis (who communicates with whom, when, and how much) is visible at the network level. Onion routing or mixnets would be required to mitigate this — out of scope for the current architecture.
Metadata minimizationThe server necessarily knows message timestamps, conversation participants, and message sizes. Sealed sender (a la Signal) is a potential future enhancement.
Post-quantum cryptographyX25519 and Ed25519 are not quantum-resistant. Migration to ML-KEM/ML-DSA is planned but not yet implemented.

Security Validation Checklist

These properties are verified continuously:
  • Only ciphertext exists in the messages table (no TEXT columns)
  • Only ciphertext traverses the wire (WebSocket payloads are BYTEA)
  • RLS blocks cross-tenant access (verified via integration tests)
  • Expired and reused invite tokens are rejected
  • Revoked devices receive 403 on all endpoints
  • No key material appears in server logs
  • Rate limits enforce enrollment and messaging boundaries
  • npm audit and pip audit show no critical vulnerabilities