CaseSolo Security Threat Model
Last updated: 2026-05-30
Overview
CaseSolo is an AI-native, multi-tenant legal case management application for personal injury firms. The repository exposes a Next.js App Router web app, dashboard APIs, client portal APIs, document upload and processing flows, AI/agent execution paths, outbound and inbound webhooks, OAuth connector callbacks, billing/subscription surfaces, and administrative God Mode operations.
The highest-value assets are legal case data, PHI/PII, privileged documents, portal messages, client expenses, settlement/financial records, OAuth tokens, webhook secrets, shared document links, audit logs, AI prompts/outputs/source spans, and firm-scoped configuration. The primary security objective is to preserve confidentiality, tenant isolation, integrity, auditability, and least privilege across every workflow.
Representative controls currently present in the repo include:
- Proxy-level authentication, RBAC checks, CSRF handling, high-risk public/API rate-limit tiers, rate-limit block telemetry, CSRF grace telemetry, and security headers in
src/proxy.ts. - Tenant-scoped query patterns and tenant Prisma helper guidance in
src/lib/db/index.ts. - Immutable audit helper in
src/lib/audit/log.ts, with high-risk audit coverage guarded bysrc/__tests__/api/immutable-audit-coverage.test.ts. - Document type and upload-size validation in
src/lib/validations/document.tsand portal upload validation insrc/app/api/portal/documents/route.ts. - Safe import-validation expression evaluation in
src/lib/import-validation/safe-expression.ts. - Crypto-backed runtime randomness in
src/lib/random.ts. - Secret-safe provider readiness documentation in
docs/dev/integration-readiness.md. - CI migration table smoke in
scripts/check-prisma-model-tables.mjs.
Threat Model, Trust Boundaries, and Assumptions
Actors
- Unauthenticated internet users can reach public marketing pages, auth routes, portal auth routes, shared document links, and provider webhook endpoints.
- Portal clients can access only their own client portal session, shared documents, messages, profile, appointments, case updates, expenses, and uploads.
- Firm users can access dashboard features according to role. They must remain scoped to their firm.
- Super admins can access God Mode and cross-firm platform operations. These actions require stronger audit and operational controls than normal firm actions.
- External providers include Stripe, Twilio, DocuSign, Adobe Sign, QuickBooks, Google Calendar, Microsoft Calendar, storage, email, AI providers, and OCR providers.
- Developers and CI can run migrations, tests, build scripts, seeds, and local tooling. Developer-only tooling must not become a production privilege bypass.
Trust Boundaries
- Browser to Next.js boundary: every API request, page navigation, form submission, cookie, header, CSRF token, search param, and JSON body is attacker-controlled until validated.
- Public route to authenticated route boundary:
src/proxy.tsdecides which routes are public and which require JWT/session authorization. - Firm tenant boundary: every data-bearing dashboard query and mutation must constrain by
firmIddirectly or through a firm-scoped parent relation. - Portal boundary: portal sessions and portal JWT/access-code flows are less privileged than firm users and must never cross into dashboard permissions.
- Shared-link boundary: public shared document tokens must be unguessable, scoped to one document, expiry-aware, and unable to enumerate tenant data.
- Document ingestion boundary: uploaded files, filenames, MIME types, OCR text, extracted entities, PDF/HTML rendering, and generated document content are attacker-controlled until sanitized and authorized.
- AI execution boundary: user prompts, case context, retrieved documents, tool inputs, model outputs, citations, and approval states cross from deterministic app logic into probabilistic external or local AI systems.
- Webhook boundary: inbound provider webhooks and outbound custom webhooks cross between CaseSolo and external systems that may retry, replay, forge, or fail.
- OAuth connector boundary: authorization URLs, callback
codeandstate, token exchange responses, refresh tokens, and provider account IDs cross from external providers into firm settings/metadata. - Storage boundary: presigned upload/download URLs and object keys cross from app authorization into object storage capabilities.
- Database/migration boundary: Prisma schema, migrations, and generated client must agree with the deployed database before deploy.
Attacker-Controlled Inputs
- HTTP headers, cookies, query strings, route params, JSON bodies, multipart upload metadata, and form submissions.
- Portal access codes, portal JWTs, shared document tokens, invitation tokens, password reset-like tokens, and OAuth callback state.
- Uploaded files, filenames, MIME types, file sizes, document text, OCR results, imported CSV rows, and validation expressions.
- AI prompts, prompt variables, document context selected for AI, agent tool inputs, generated output that may later be rendered, exported, emailed, or approved.
- Webhook payloads, signatures, replay attempts, delivery URLs, webhook event subscriptions, and custom API/webhook wizard config.
- OAuth provider responses, realm/account IDs, token expiry metadata, and disconnected/reconnected state.
Invariants
- No authenticated firm user may read or mutate another firm's cases, contacts, documents, tasks, settings, workflows, webhooks, billing records, or audit records.
- Portal clients may only access cases/documents where
firmIdandclientIdor a scoped share token proves authorization. - Public shared links and portal links must not disclose whether unrelated records exist.
- High-risk mutations must be auditable with actor, firm, entity, entity id, timestamp, and relevant metadata.
- OAuth tokens, webhook secrets, API keys, JWT secrets, client secrets, and provider credentials must never be returned to browsers, logs, readiness APIs, or support payloads.
- Uploaded documents must be validated for type and size before storage and must not become executable script content in app-rendered pages.
- AI output that affects legal strategy, client communications, documents, settlement/financial decisions, or workflow automation requires provenance, citations/source context where applicable, and human approval before consequential action.
- Webhook deliveries must be signed outbound and verified inbound where provider signatures are available.
- Migrations must create every Prisma model table before deployment continues.
Attack Surface, Mitigations, and Attacker Stories
AI Tool Execution
Primary surfaces include src/app/api/ai/analyze/route.ts, src/app/api/agents/invoke/route.ts, src/lib/ai/execute.ts, src/lib/ai/truth-guard.ts, src/lib/ai/context-builder.ts, and case-specific AI routes such as src/app/api/cases/[caseId]/ai-doc-generation/route.ts.
Relevant attacker stories:
- A firm user attempts prompt injection through uploaded documents or case notes so AI output includes hidden instructions, leaks unrelated context, or triggers unsafe workflow automation.
- A compromised portal/client input is included in case context and later influences AI-generated legal documents.
- An attacker tries to exhaust AI credits or queue capacity through repeated AI calls.
- A user attempts to bypass approval by directly calling an API action that marks AI output approved.
Mitigation requirements:
- Build AI context from firm-scoped records only.
- Treat retrieved document text and prompt variables as untrusted data.
- Keep credit checks, AI/agent-specific rate limits, and role checks around AI endpoints.
- Keep truth-guard, citation, approval, and audit metadata attached to consequential AI outputs.
- Do not auto-execute destructive or client-visible AI actions without an approval checkpoint and audit record.
Document Ingestion and Rendering
Primary surfaces include dashboard upload routes, portal document upload/completion, document analysis/OCR, generated PDFs, shared documents, document viewer components, and storage URL helpers.
Relevant attacker stories:
- A portal client uploads a file with a misleading MIME type, oversized payload, dangerous filename, embedded active content, or malicious PDF/HTML payload.
- A user attempts to access a pending upload or failed upload from another tenant.
- A shared document token is guessed, reused after expiry, or used to infer document existence.
- OCR or extracted text is rendered without escaping and becomes stored XSS.
Mitigation requirements:
- Enforce MIME/type allowlists, size limits, and filename normalization.
- Use pending/complete upload state so partially uploaded storage objects do not become visible documents.
- Keep all document reads scoped by
firmIdand case/client ownership. - Render generated HTML only through controlled code paths; never inline arbitrary uploaded HTML as trusted app markup.
- Audit upload request, upload completion, document updates, sharing, signing, and deletion.
Webhooks
Primary surfaces include src/app/api/webhooks/*, src/app/api/settings/webhooks/route.ts, src/app/api/webhooks/deliver/route.ts, src/lib/webhooks/deliver.ts, and src/lib/webhooks/webhook-dispatcher.ts.
Relevant attacker stories:
- An attacker forges an inbound provider webhook to change signature, payment, calendar, or messaging state.
- A malicious admin configures outbound webhooks to internal network targets or sensitive URLs.
- A legitimate provider retries an event and causes duplicate state changes.
- A webhook replay or test delivery leaks case data to the wrong endpoint.
Mitigation requirements:
- Verify provider signatures or challenge tokens where available.
- Keep public webhook endpoints rate-limited at the proxy before handler-level signature verification.
- Make webhook handlers idempotent where provider event IDs exist.
- Store and display delivery health without leaking secrets.
- Sign outbound webhooks with HMAC and use crypto-backed delivery IDs.
- Audit manual replay/test delivery and configuration changes.
- Consider SSRF protections for custom outbound webhook URLs before expanding custom adapters.
OAuth Connectors
Primary surfaces include OAuth route families under src/app/api/integrations/, connector libraries under src/lib/integrations/, and integration readiness docs/API.
Relevant attacker stories:
- An attacker tampers with OAuth
stateor callback params to bind the wrong provider account to a firm. - A disconnected or expired token still appears healthy, causing silent data loss or stale sync.
- OAuth credentials or refresh tokens are returned in readiness APIs or logs.
- A cross-tenant callback updates another firm's settings.
Mitigation requirements:
- Store and validate OAuth state per firm/user before token exchange.
- Scope callback updates by authenticated state and firm-owned settings only.
- Never return tokens, client secrets, webhook secrets, or provider raw credentials to the browser.
- Track token expiry, last sync, provider account identity, and disconnect state.
- Add replayable failure logs and user-visible recovery actions in the Integration Reliability Center.
Public Portal Links and Shared Documents
Primary surfaces include src/lib/auth/portal-session.ts, src/lib/auth/portal-jwt.ts, src/lib/auth/portal-client.ts, src/app/api/portal/*, src/app/api/portal/admin/shared-documents/route.ts, and src/app/api/shared/[token]/route.ts.
Relevant attacker stories:
- A client modifies route params or request body fields to access another client's case, messages, documents, expenses, or appointments.
- A shared token is brute forced or replayed after a case relationship changes.
- A portal access code or JWT is used as a dashboard credential.
- A public shared route leaks metadata for missing or unauthorized documents.
Mitigation requirements:
- Portal APIs must prove
firmIdpluscontactId/clientIdownership before returning case data. - Shared token handlers should use opaque, high-entropy tokens, expiry checks, and non-enumerating errors.
- Portal identities must remain separate from staff/dashboard identities unless explicitly linked and role-checked.
- Portal profile, message, document, expense, and access-code changes must be audited.
- Rate-limit portal auth and token redemption paths.
Severity Calibration
Critical
Critical issues allow cross-tenant data access, unauthorized Super Admin/God Mode action, arbitrary execution in production, credential/token disclosure, payment/trust-account tampering, or unaudited destructive legal-record mutation.
Examples:
- A document, case, portal, or AI endpoint accepts an ID and returns another firm's data without a
firmIdor firm-owned parent check. - An OAuth callback can bind attacker-controlled provider credentials to another firm.
- A public shared document token can be enumerated or bypasses expiry and firm ownership.
- A webhook can forge payment/signature status without signature verification and mutate records.
High
High issues compromise one tenant, enable privilege escalation within a firm, bypass approval/audit for consequential actions, or expose sensitive records through logs or support/readiness payloads.
Examples:
- A portal client can update another client's profile, expense, upload, or message within the same firm.
- An AI-generated document can be marked approved or exported without role checks and immutable audit.
- OAuth or webhook secrets are returned to dashboard clients.
- Outbound webhook configuration permits sensitive data exfiltration without visible delivery logs and audit.
Medium
Medium issues require an already-authenticated user, limited data sensitivity, meaningful user interaction, or produce integrity/availability impact without broad data compromise.
Examples:
- Missing idempotency causes duplicate webhook processing for non-financial events.
- A route leaks whether a record exists across tenants without returning full content.
- AI credit exhaustion is possible within a firm because an endpoint lacks a stricter rate tier.
- A document ingestion path accepts unsupported content that fails processing but does not expose data.
Low
Low issues have limited security impact, affect developer-only paths, expose non-sensitive metadata, or are mostly defense-in-depth gaps.
Examples:
- A planning or docs artifact has stale security wording but code/tests remain correct.
- A CI-only script has weak error text but no production exposure.
- A route returns inconsistent non-sensitive validation messages.
- A UI-only state bug makes an already-authorized action confusing but does not bypass server checks.