Spaces:
Running
Download docs/security.md from Benaah/MicProtocol: direct link, hf CLI and curl.
- Browser
- Download file 11 kB
-
https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/docs/security.md
- Command line
-
hf download hf://spaces/Benaah/MicProtocol/docs/security.md
-
curl -L -o security.md https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/docs/security.md
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 byBetterAuthGuardon every protected endpoint viaBetterAuthService.getSessionFromHeaders(). - Workspace scoping: Resolved from the authenticated user's
WorkspaceMembermemberships; thehasWorkspacetRPC middleware enforces the required role. - Dev mode bypass: If
DEV_AUTH_BYPASS_ENABLED=trueandNODE_ENV=development, the API accepts anx-user-idheader 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/VerificationPrisma 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 viaWorkspaceMember.role. - Scope: Every domain query chains through
workspace β podcast β entity. The synthetic agent suite explicitly tests cross-workspace isolation inscripts/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 withMIC_REALTIME_SHARED_SECRET(mic-realtime). - Socket.io
/eventshardening: handshake origins follow the same policy as HTTP CORS (common/origin-policy.tsβ explicit origins +*.ROOT_DOMAINsubdomains), 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;.gitignoreexcludes it). - Generation:
bash scripts/generate-secrets.shproduces 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).
- Never rotate after initial setup: every
- 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_logstable (per SOC2 CC6). Implemented viaAuditService(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-Timecarries duration. - Telemetry endpoints:
/tracing/spans(recent spans + p95),/tracing/metrics(counts, error rate). Surfaced in the Admin app at/monitoringand/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:
- Set every
*_WEBHOOK_SECRET(empty values silently disable verification). - Sync secrets on both sides when rotating.
- Restrict by source IP where the upstream publishes known egress ranges.
- Monitor 401 rates from the webhook controller.
- 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.