Architecture

Security Model

MCP Ambassador is designed with defense-in-depth. Every layer independently enforces security — authentication, authorization, encrypted credential storage, audit logging, and kill switches.


Security principles

  1. Zero trust — every request is authenticated and authorized, no implicit trust
  2. Least privilege — users get the minimum tool set required for their role
  3. Defense in depth — authentication, authorization, audit, rate limiting, kill switches
  4. Credential isolation — downstream MCP credentials never leave the server; clients never see them
  5. Encryption in transit — TLS for all client-server and server-MCP communication
  6. Encryption at rest — secrets encrypted in the backing store (AES-256-GCM)
  7. Audit everything — every tool call, every auth decision, every config change

Credential vault

Per-user credential storage uses AES-256-GCM with HKDF key derivation.

How it works:

  1. Server generates a master key on first boot (32 bytes, stored at $DATA_DIR/credential_master_key, permissions 0600)
  2. Each user gets a unique vault_salt (32 bytes, stored in the users table)
  3. When a user enters credentials for an MCP:
    • User key = HKDF(master_key, salt=vault_salt, info="mcpambassador-credential-vault-v1")
    • Encrypted = AES-256-GCM(user_key, plaintext=credentials)
    • Stored in user_credentials table with IV
  4. When spawning a per-user MCP:
    • Decrypt credentials with user's derived key
    • Inject into MCP process environment
    • Zero memory after use

Threat model (Community tier):

ScenarioProtected?
Stolen database alone✅ Cannot decrypt (needs master key + user salt)
Stolen master key alone✅ Cannot decrypt (needs database + salt)
Database + master key stolen⚠️ Full compromise (accepted for community tier)

Session security

Sessions use HMAC-SHA256 signed tokens:

  • Preshared key (amb_pk_) — admin-issued, stored by developer in config
  • Session token (amb_st_) — ephemeral, issued on registration, expires after idle timeout
  • Session secret — HMAC signing secret, persisted to survive server restarts
  • Cookie securityhttpOnly, secure, sameSite: strict for web UI sessions

Login rate limiting: 5 attempts per IP per 5 minutes.


Password security

User passwords are hashed with Argon2id:

  • Argon2id is the recommended algorithm from OWASP and the Password Hashing Competition
  • Minimum password strength: score 3+ (zxcvbn), 12+ characters
  • Passwords compared using crypto.timingSafeEqual to prevent timing attacks
  • Session ID regenerated on login to prevent session fixation

Transport security

TLS is always on:

  • Development: Auto-generated self-signed certificates on first boot (TOFU model)
  • Production: Configure CA-signed certificates via environment variables
  • Client trust: Client receives server's CA fingerprint on first registration; must confirm trust

Content Security Policy

The React SPA enforces strict CSP headers:

  • No inline scripts (all code in external bundles)
  • Source maps removed from production build
  • CSRF protection via sameSite: strict cookies + double-submit cookie pattern

Security audit history

MCP Ambassador underwent multiple security reviews during development:

  • ADR-001/003 review — Resolved findings F-001 through F-005 (timing attacks, session fixation)
  • Architecture review — Resolved findings F-006 through F-016 (credential handling, key management)
  • M26 credential vault review — Resolved race conditions, memory zeroing, env var injection
  • Phase 3 review — Resolved CSP, source maps, dependency audit (0 vulnerabilities)

0.8.0-beta.1 ships with 327 passing tests covering authentication, RBAC, credential vault, and full subscription lifecycle.


Responsible disclosure

Found a security issue? Please report it via GitHub Issues with the security label, or contact the maintainers directly. Do not disclose publicly until a fix is available.

Previous
Client & Server