MicProtocol / docs /security.md
Benaah's picture
Upload folder using huggingface_hub
b17baae verified
|
Raw History Blame Contribute Delete
11 kB

Security & Compliance

This doc covers the security model, threat surface, and regulatory compliance posture of MicProtocol. It complements Webhooks (per-webhook auth) and Operations Runbook (incident response).

Authentication

  • Provider: Better Auth β€” handles session management, OAuth (Google, Apple), password hashing, email verification, and device sessions.
  • Tokens: Session cookie better-auth.session_token (httpOnly, SameSite=Lax). Verified by BetterAuthGuard on every protected endpoint via BetterAuthService.getSessionFromHeaders().
  • Workspace scoping: Resolved from the authenticated user's WorkspaceMember memberships; the hasWorkspace tRPC middleware enforces the required role.
  • Dev mode bypass: If DEV_AUTH_BYPASS_ENABLED=true and NODE_ENV=development, the API accepts an x-user-id header containing a user UUID. Used by the synthetic agent runner and local dev. Never expose this in production β€” the auth guard rejects it unless both conditions are met.
  • Webhook secret: Not applicable to Better Auth β€” user lifecycle events are handled via the Session/Account/Verification Prisma models directly.
  • OAuth flows: Google Calendar (GOOGLE_CLIENT_*), Nylas (NYLAS_CLIENT_*) for Google/Outlook/Exchange, with explicit redirect URIs in .env.

Authorization

  • Role hierarchy: Owner > Admin > Editor > Viewer. Workspace-level role assignment via WorkspaceMember.role.
  • Scope: Every domain query chains through workspace β†’ podcast β†’ entity. The synthetic agent suite explicitly tests cross-workspace isolation in scripts/synthetic-agents/scenarios/cross-workspace.ts.
  • Guest portal: signed-token auth (HMAC-SHA256 with a workspace-specific secret, 7-day expiry, granular scope). No tenant-level access from guest tokens.

Transport Security

  • TLS 1.3 minimum on all production connections (enforced by Clerk, Resend, R2, Nylas; verify at your reverse proxy).
  • HSTS with preload β€” set on the edge proxy serving web + guest portal.
  • WS auth: WebSocket connections require a JWT in Authorization (Socket.io) or a JWT signed with MIC_REALTIME_SHARED_SECRET (mic-realtime).
  • Socket.io /events hardening: handshake origins follow the same policy as HTTP CORS (common/origin-policy.ts β€” explicit origins + *.ROOT_DOMAIN subdomains), incoming message payloads are capped at 64 KB, join:* payloads are shape-validated, and per-socket join rate limiting (30/min) bounds DB lookups.

Data Isolation

Layer Mechanism
Application Every query filters podcastId β†’ workspaceId; no cross-workspace join possible from the API code path
Database Row-Level Security (RLS) enabled on tenant-scoped tables (workspaces, workspace_members, podcasts, diaries, workspace_branding_settings, workspace_settings, workspace_integrations, conversations, tasks, media_comments). Policies scope rows to current_setting('app.workspace_id', true)::uuid. Set via RLSMiddleware on each authenticated request. Migration: 20261023000001_enable_rls.
Object storage Per-tenant prefixes in the shared micprotocol-storage bucket; presigned URLs with 15-minute expiry

The workspace β†’ podcast β†’ guest hierarchy is the foundation of complete data isolation. See Database Schema β†’ Row-Level Security.

Secrets Management

  • Single source of truth: .env (never committed; .gitignore excludes it).
  • Generation: bash scripts/generate-secrets.sh produces strong random values for every required secret.
  • Rotation policy:
    • Never rotate after initial setup: every *_ENCRYPTION_KEY, *_NEXTAUTH_SECRET, CALCOM_ENCRYPTION_KEY, DOCUMENSO_ENCRYPTION_KEY/SECONDARY_KEY, FORMBRICKS_ENCRYPTION_KEY, FORMBRICKS_HUB_API_KEY, FORMBRICKS_CUBE_API_SECRET. Rotation invalidates all encrypted data and sessions.
    • Rotatable on a schedule: *_WEBHOOK_SECRET, FORMBRICKS_CRON_SECRET, UMAMI_APP_SECRET, Mongo/Redis passwords, SMTP credentials.
    • Rotatable via UI: per-integration admin tokens (CALCOM_API_KEY, FORMBRICKS_API_KEY, LISTMONK_API_TOKEN, CHATWOOT_API_KEY).
  • Production: store in AWS Secrets Manager or equivalent; inject at container start, never bake into images.

File Uploads

Concern Implementation
Access Presigned R2/MinIO URLs, 15-minute expiry, single-use
MIME verification Content-Type checked against allowlist on ingest
Virus scanning ClamAV scan on ingest (see deployment architecture doc)
Size limits Enforced at the proxy and in the upload handler
Storage class R2 Standard by default; lifecycle rules for archival if needed

See Architecture β†’ Data Security.

Rate Limiting

Redis-backed rate limiter with two tiers:

Scope Limit Configurable via
Per IP (anonymous + guest portal) 100 req/min RATE_LIMIT_TTL, RATE_LIMIT_MAX
Per authenticated workspace 1000 req/min tRPC rate-limit middleware
Per WebSocket 120 messages/min MIC_REALTIME_RATE_LIMIT

429 responses include a Retry-After header. Synthetic agents surface rate-limit gaps in weaknesses.json.

Logging & Audit

  • Audit log: every write operation emits an audit event to an append-only audit_logs table (per SOC2 CC6). Implemented via AuditService (best-effort writes, never blocks the request path). Migration: 20261023000000_add_audit_log.
  • Trace propagation: X-Trace-Id (tr-xxxxxxxx) crosses services and clients; X-Response-Time carries duration.
  • Telemetry endpoints: /tracing/spans (recent spans + p95), /tracing/metrics (counts, error rate). Surfaced in the Admin app at /monitoring and /analytics.
  • No PII in logs: the logger redacts known PII fields (email, phone) before emitting.
  • Integrations: optional Sentry (SENTRY_DSN) and LogRocket (LOGROCKET_APP_ID) for error tracking and session replay.

Privacy & Compliance

MicProtocol is built to comply with GDPR (EU), POPIA (South Africa), Kenya DPA 2019, and Nigeria NDPR. Features supporting these regimes:

Requirement Implementation
Right to erasure Cascade workflow that anonymises guest PII across episodes, messages, and assets while preserving aggregate analytics
Data minimisation Only fields required for outreach and booking are collected; open-ended custom fields lock behind workspace admin approval
Consent tracking Outreach sequences record processing basis (legitimate interest) and flag sequences where unsubscribe was received
Email compliance CAN-SPAM footer injection, List-Unsubscribe headers, automatic unsubscribe on .unsubscribe event
Data residency Workspace billing tier unlocks the ability to specify R2 storage region (incl. Africa South / Johannesburg edge)
Breach notification Operational runbook covers incident communication (see Operations Runbook)

Mobile-Specific Security

  • Certificate pinning on all API calls (configurable per environment).
  • Secure storage: Keychain (iOS) / Keystore (Android) for tokens and secrets.
  • Biometric authentication (FaceID/TouchID) opt-in.
  • Jailbreak/root detection β€” refuses to run on compromised devices in production builds.
  • Obfuscation ready for production builds (EAS Build).

See apps/mobile/FEATURES.md for the full mobile security checklist.

Webhook Security

Every inbound webhook uses crypto.timingSafeEqual() for HMAC signature verification β€” no timing side-channels. See Webhooks β†’ Security Model for the catalog and the per-provider checklist. LiveKit is the exception: it authenticates via a Bearer JWT (iss = LIVEKIT_API_KEY, HS256 with LIVEKIT_API_SECRET) whose sha256 claim is verified over the raw request body.

Critical production safeguards:

  1. Set every *_WEBHOOK_SECRET (empty values silently disable verification).
  2. Sync secrets on both sides when rotating.
  3. Restrict by source IP where the upstream publishes known egress ranges.
  4. Monitor 401 rates from the webhook controller.
  5. Never expose webhooks over plain HTTP.

Vulnerability Detection

The synthetic agent framework (scripts/synthetic-agents/) continuously probes the API surface for known weakness categories:

  • Auth guard gaps (missing role checks)
  • Input validation failures (Zod schema mismatches, type coercion)
  • Rate limit gaps (per-IP vs per-workspace)
  • Subscription gating failures (paid features reachable on free tier)
  • Privilege escalation (viewer β†’ admin)
  • Workspace boundary leaks

Run a full sweep before any release:

pnpm agents:run

Findings categorised by severity in scripts/synthetic-agents/weaknesses.json. See the Synthetic Agents Testing section of the docs index.

Known Threats & Mitigations

Threat Mitigation
Token enumeration on guest portal Per-IP rate limit (10 req/min) on /portal/*
Cross-workspace data leak workspaceId filtering in every query handler; RLS at DB layer
Webhook replay WebhookIdempotencyService dedupes via deterministic event keys
Route shadowing (duplicate endpoint) RouteCollisionService fails API startup when two handlers register the same method + path
Subprocess injection (CLIP scorer) execFile with argv (no shell); assertSafeUrl validates the video URL before download
Secrets in client bundles Only NEXT_PUBLIC_* vars exposed to web; all others server-side only
CSRF on mutations tRPC + SameSite cookies; Better Auth session cookie defaults
Server-side request forgery apps/api/src/common/safe-fetch.ts validates URLs against an allowlist before fetch

Security Checklist for Releases

Stage Check
Pre-merge pnpm agents:run passes; no new entries in weaknesses.json
Pre-deploy All *_WEBHOOK_SECRET set; no *_ENCRYPTION_KEY is empty; BETTER_AUTH_SECRET set; MIC_REALTIME_*_SECRET set
Post-deploy /health/detailed returns green; /integrations/health returns green for every integration in use
Quarterly Rotate webhook secrets; review audit_log for anomalies; test backup restoration
Annually Penetration test webhook + portal endpoints; review access logs for stale service accounts

Reporting Vulnerabilities

Internal reports: file a security-labeled issue in the repo with reproduction steps. External reports (researchers): contact the platform team via the security contact in the Admin app.