Security

Security

Owner: Engineering Last reviewed: 2026-Q2

This document captures our current security posture and concrete guardrails implemented in this repo, plus recommended hardening steps. It focuses on authN/Z, user data isolation, file handling, data protection, infrastructure, and developer practices.

Overview

  • Threat model: user-scoped SaaS where users manage boards, action points, shares, and documents. High-value assets: documents (and extracted text/embeddings), user identities, workspace metadata, board permissions, and action-point shares.
  • Primary risks: cross-tenant data access, insecure file uploads, SSRF via URL-based analysis, credential leakage, dependency and container vulnerabilities.

Authentication

  • Provider: Clerk. Frontend obtains tokens via Clerk React SDK.
  • Verification: Backend verifies JWT via Clerk JWKS with caching (backend/py/core/authentication.py).
    • Validates signature (RS256), exp, nbf, and iss.
    • Authorized party: validate azp against CLERK_AUTHORIZED_PARTIES when configured.
    • Extracts ClerkUser context: clerk_user_id, email/name fields, plan claim, and subscription status.

Authorization

  • Dual model (ADR-001):
    • get_current_user()ClerkUser for role/permissions checks.
    • get_current_db_user() → local User (JIT provisioned) for DB relationships.
  • Enforce ownership and explicit grants for boards, action points, and documents.
  • Use core/authorization.py helpers; never rely solely on client hints.

Tenant Isolation

  • User-scoped entities use local User.id ownership and grant tables rather than Clerk organization IDs.
  • All queries returning protected data must filter through ownership, BoardPermission, ActionPointShare, or document permissions for the current local User.
  • Guard against cross-user access attempts; return 404 where existence should not be disclosed and log security-relevant events.

CORS & Security Headers

  • CORS origins depend on ENVIRONMENT in backend/py/main.py (prod/staging allow specific domains; dev allows localhost).
  • Security headers middleware adds:
    • X-Frame-Options: DENY
    • X-Content-Type-Options: nosniff
    • X-XSS-Protection: 1; mode=block (legacy)
    • Strict-Transport-Security enabled for non-dev (HSTS)

Input Validation & File Handling

  • File validation in backend/py/core/config.py:
    • Size limits: per file and per session
    • Allow-list by MIME and extension with mismatch checks
    • Clear error messages for invalid content
  • Quarantine-first pattern (backend/py/services/quarantine_service.py):
    • Upload to quarantine container → Defender for Storage scans → promote to files or delete infected
    • Feature flags: ENABLE_VIRUS_SCAN, ENABLE_QUARANTINE
  • Storage access via time-limited SAS URLs; never trust client-provided MIME or metadata.
  • Hashing/deduplication: Document.content_hash used to detect duplicates.

Document & AI Integrations

  • External services: Azure OpenAI, Vision, Document Intelligence. Always set timeouts and handle retries (httpx with sane defaults).
  • URL-based analysis endpoints (e.g., analyze_url) are SSRF-prone. Required hardening:
    • Block link-local, RFC1918, and metadata IPs; allow-list schemes and domains if possible.
    • Enforce max download size and content-type allow-list when fetching remote content.

Data Protection

  • Database: Azure PostgreSQL with TLS enforced.
    • Async engine uses SSL context; sync URL includes sslmode=require (backend/py/db/database.py).
  • At-rest encryption:
    • Azure Blob Storage provides SSE.
    • Application-level envelope encryption fields exist (Document.encrypted_dek, encryption_key_id; Organization.kek_key_id). Implement/maintain KEK/DEK rotation policy.
  • Avoid storing secrets or PII in logs; mask sensitive values.

Secrets & Configuration

  • Backend env template: backend/py/env.example (DB, Clerk, Azure OpenAI/Vision/Doc Intelligence, Storage, SP credentials).
  • Frontend env template: frontend/env.example.
  • Store secrets in Azure DevOps variable groups and/or Azure Key Vault; do not commit secrets. Rotate keys regularly.

Logging, Audit, and Monitoring

  • Audit logging model in models (AuditLog) and security event enums (SecurityEventType, AlertSeverity).
  • Prefer structured logs with request IDs (X-Request-ID allowed in CORS headers).
  • Observability: use OpenTelemetry libs to emit traces/metrics to Azure Monitor.
  • Health endpoints: /health/live, /health/ready, /health/status, /health/metrics.
  • Rate limiting: add per-route limits (e.g., Redis + token bucket) especially for embeddings and upload routes.
  • Request size/time limits: enforce maximum payload sizes and timeouts at app and reverse-proxy layers.
  • Input schemas: use Pydantic constraints (length/pattern) and explicit enums where applicable.
  • Error handling: avoid leaking internals; map to consistent HTTP responses (core/errors.py).
  • Idempotency: use idempotency keys for repeatable operations where appropriate.
  • Keep dependencies pinned and updated; run pip-audit and npm audit in CI.
  • Container images: use minimal base images and run as non-root; enable ACR image scanning.
  • SBOM generation for backend/frontend images; track CVEs and patch promptly.

Incident Response

  • Prioritize containment and mitigation. Roll back by redeploying the previous image tag.
  • Use incident-response.md for severity, roles, communications, and postmortems.
  • Capture a brief postmortem with root cause, impact, timeline, and specific follow-ups.
  • Add detection rules/dashboards for similar events; update the handbook if controls change.

Developer Security Checklist

  • AuthN/Z: use get_current_user and/or get_current_db_user correctly; verify user-scoped filters and permission grants.
  • Input validation: Pydantic constraints; never trust client MIME/types.
  • Files: respect size/MIME allow-list; prefer quarantine flow; generate SAS server-side.
  • Secrets: load from environment/Key Vault; never log secrets.
  • External calls: set timeouts, retries, and sane limits.
  • Observability: add logs/traces; ensure health checks cover new dependencies.
  • Docs: update ADRs and this page when adding sensitive flows or controls.

Next Improvements (Backlog)

ItemOwnerTargetTracking
Implement SSRF protections for URL-based analysis endpoints: network blocklist/allow-list, resolver checksBackend Engineering2026-Q3Create issue before enabling broad URL ingestion
Introduce global and per-user rate limiting for expensive APIsBackend Engineering2026-Q3Track with API hardening work
Enforce KEK/DEK rotation and document the key management SOPEngineering + Security owner2026-Q4Track with data-protection work
Add automated dependency and container scanning jobs in pipelinesEngineering + DevOps owner2026-Q3Track with CI/CD hardening