Skip to main content
Terra is built with security as a foundational principle. This document outlines our security architecture, threat model, and practices to ensure government-grade compliance and enterprise readiness.

πŸ›‘οΈ Table of Contents

  1. Security Architecture
  2. Threat Model
  3. Authentication & Authorization
  4. Data Protection
  5. Audit & Compliance
  6. Vulnerability Reporting
  7. Security Best Practices

πŸ—οΈ Security Architecture

Defense-in-Depth Strategy

Terra implements multiple layers of security controls:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Layer 1: Network & Infrastructure                          β”‚
β”‚ β€’ CloudFlare DDoS protection                                β”‚
β”‚ β€’ TLS 1.3 encryption in transit                            β”‚
β”‚ β€’ Geographic access controls (optional)                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Layer 2: Application Security                              β”‚
β”‚ β€’ CSP headers (Content Security Policy)                    β”‚
β”‚ β€’ HSTS (HTTP Strict Transport Security)                    β”‚
β”‚ β€’ XSS protection via DOMPurify                             β”‚
β”‚ β€’ CSRF protection via Next.js                              β”‚
β”‚ β€’ Rate limiting on public endpoints                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Layer 3: Authentication & Authorization                    β”‚
β”‚ β€’ WorkOS SSO with MFA support                              β”‚
β”‚ β€’ Role-Based Access Control (RBAC)                         β”‚
β”‚ β€’ Session encryption (JWT with secure cookies)             β”‚
β”‚ β€’ Row-Level Security (RLS) in database                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Layer 4: Data Security                                     β”‚
β”‚ β€’ Encryption at rest (AES-256)                             β”‚
β”‚ β€’ Encrypted submission data (sensitive fields)             β”‚
β”‚ β€’ PII redaction in logs                                    β”‚
β”‚ β€’ Secure file storage with signed URLs                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Layer 5: Monitoring & Audit                                β”‚
β”‚ β€’ Comprehensive audit logging                               β”‚
β”‚ β€’ Real-time security event monitoring (Sentry)             β”‚
β”‚ β€’ Access logs with IP tracking                             β”‚
β”‚ β€’ Automated vulnerability scanning                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Security Components

Middleware Security (src/middleware.ts)

  • Purpose: First line of defense for all HTTP requests
  • Controls:
    • CSP header injection with nonce-based script execution
    • Role-based route protection (admin vs. user)
    • Session decryption and validation
    • Multi-tenant domain routing
    • Redirect validation (prevents open redirects)
  • Fail-Secure: Defaults deny access, requires explicit session

Auth Guards (src/lib/auth-guards.ts)

  • requireAdmin() - Blocks non-admin users
  • checkFormAccess() - Verifies form ownership/team membership
  • verifySubmissionAccess() - Ensures submission ownership

Security Utilities (src/lib/security/)

  • Integration Validator - Prevents XSS in third-party integration IDs
  • Submission Guard - Verifies resource ownership for sensitive operations
  • Path Sanitization - Prevents path traversal in file operations

🎯 Threat Model

Assets Protected

AssetSensitivityProtection Mechanisms
User CredentialsCRITICALWorkOS SSO, encrypted sessions, MFA support
Submission DataHIGHEncryption at rest, RLS policies, access controls
Form ConfigurationsMEDIUMRBAC, audit logging, version control
API KeysCRITICALEnvironment variables, never logged, rotation support
File UploadsMEDIUMSigned URLs, type validation, size limits, access controls
Audit LogsHIGHTamper-evident, retention policies, admin-only access

Threat Actors

1. External Attackers (Untrusted)

  • Goal: Data theft, service disruption, unauthorized access
  • Mitigations:
    • Rate limiting on public endpoints
    • DDoS protection (CloudFlare)
    • Input validation on all server actions
    • CSP to prevent XSS
    • SQL injection prevention (parameterized queries via Supabase)

2. Malicious Insiders (Low-Privilege Users)

  • Goal: Privilege escalation, access other users’ data
  • Mitigations:
    • RBAC enforcement in middleware
    • Row-level security in database
    • Submission ownership verification
    • Audit logging of all actions
    • Fail-secure auth guards

3. Compromised Accounts (Legitimate Users)

  • Goal: Abuse stolen credentials
  • Mitigations:
    • Session expiration (configurable)
    • MFA enforcement (WorkOS)
    • Anomaly detection in audit logs
    • IP tracking and geo-blocking (optional)

4. Supply Chain Attacks (Dependencies)

  • Goal: Inject malicious code via npm packages
  • Mitigations:
    • Automated dependency scanning (npm audit, Snyk)
    • Lock files (pnpm-lock.yaml)
    • Regular security updates
    • Minimal dependency footprint

Attack Vectors & Mitigations

Attack VectorRisk LevelMitigation Status
SQL InjectionHIGHβœ… Mitigated - Supabase client uses parameterized queries
XSS (Cross-Site Scripting)HIGHβœ… Mitigated - DOMPurify + CSP + input validation
CSRF (Cross-Site Request Forgery)MEDIUMβœ… Mitigated - Next.js built-in protection
Path TraversalMEDIUMβœ… Mitigated - Path sanitization in file operations
Privilege EscalationHIGHβœ… Mitigated - RBAC + RLS + auth guards
Session HijackingMEDIUMβœ… Mitigated - Encrypted cookies + HTTPS only
Data Exposure via APIHIGHβœ… Mitigated - Auth guards + submission ownership checks
Rate Limit BypassLOW⚠️ In Progress - Adding rate limiting
Account EnumerationLOWβœ… Mitigated - Generic error messages
Open RedirectLOWβœ… Mitigated - Redirect validation in middleware

πŸ” Authentication & Authorization

Authentication Flow (WorkOS SSO)

1. User visits /login
     ↓
2. Redirected to WorkOS Auth0 (OAuth 2.0)
     ↓
3. User authenticates (email/password + MFA if enabled)
     ↓
4. WorkOS callback with authorization code
     ↓
5. Terra exchanges code for user profile + tokens
     ↓
6. Session created (encrypted JWT in HTTP-only cookie)
     ↓
7. User redirected to dashboard or portal based on role

Role-Based Access Control (RBAC)

RolePermissionsRoutes
super_adminFull system access, can manage all forms/usersAll routes
adminManage forms, view submissions, configure settings/forms, /applications, /settings
userLimited access (reserved for future use)/portal
applicantView own submissions only/portal

Authorization Enforcement

Middleware-Level (Route Protection)
// src/middleware.ts
// Runs on EVERY request before page render
if (isAdminRoute && !hasAdminAccess(userRole)) {
  redirect("/portal"); // Deny access
}
Action-Level (Resource Protection)
// src/app/actions/*.ts
// Runs on EVERY server action before execution
const auth = await checkFormAccess(formId);
if (!auth.success) {
  return { success: false, error: "Unauthorized" };
}
Database-Level (Row-Level Security)
-- Supabase RLS policies ensure even direct DB queries are filtered
CREATE POLICY "Users can only view their own submissions"
  ON submissions FOR SELECT
  USING (user_id = auth.uid());

πŸ”’ Data Protection

Encryption

In Transit

  • TLS 1.3 for all HTTPS connections
  • Certificate pinning (optional for high-security deployments)
  • No downgrade attacks - HSTS enforced

At Rest

  • Database: AES-256 encryption (Supabase managed)
  • File Storage: AES-256 encryption (Supabase Storage)
  • Sensitive Fields: Additional application-level encryption for:
    • Bank account numbers
    • Routing numbers
    • Social security numbers
    • Plaid access tokens

In Use

  • Memory: Secrets loaded from environment variables, never hardcoded
  • Logs: PII automatically redacted by logger (src/lib/logger.ts)

Data Classification

Data TypeClassificationEncryptionRetention
User CredentialsCRITICALWorkOS managedUntil account deletion
Submission DataHIGHAt rest (AES-256)Configurable (default: indefinite)
Audit LogsMEDIUMAt rest (AES-256)2 years (compliance)
Form SchemasLOWAt rest (AES-256)Indefinite
File UploadsMEDIUMAt rest (AES-256)Linked to submission

PII Handling

Terra follows GDPR/CCPA principles:
  1. Data Minimization - Only collect necessary data
  2. Purpose Limitation - Data used only for stated purpose
  3. Storage Limitation - Configurable retention policies
  4. Integrity & Confidentiality - Encryption + access controls
  5. Right to Erasure - Users can delete their data
PII Redaction in Logs:
// src/lib/logger.ts automatically redacts:
- Emails
- Phone numbers
- SSNs
- Credit card numbers
- API keys / tokens
- Passwords

πŸ“Š Audit & Compliance

Audit Logging

Every mutation operation is logged:
// Example: Form published
logFormAudit("publish", formId, userId, userEmail, userRole, {
  form_title: "Application Form",
});
Audit Log Schema:
  • Who: user_id, user_email, user_role
  • What: action_type (create, update, delete, etc.)
  • Which: entity_type, entity_id
  • When: created_at (UTC timestamp)
  • Where: ip_address, user_agent
  • Why: metadata (context)
  • Changes: changes (before/after diff)
Audit Log Retention: 2 years minimum (configurable via migration 079)

Compliance Frameworks

SOC 2 Type II (System and Organization Controls)

  • βœ… CC6.1 - Logical access controls (RBAC, RLS)
  • βœ… CC6.6 - Audit logging and monitoring
  • βœ… CC6.7 - Encryption at rest and in transit
  • βœ… CC7.2 - Change management (audit logs + version control)

ISO 27001 (Information Security Management)

  • βœ… A.9 - Access control (authentication, authorization)
  • βœ… A.10 - Cryptography (TLS, AES-256)
  • βœ… A.12 - Operations security (logging, monitoring)
  • βœ… A.14 - System acquisition and development (secure SDLC)

GDPR (General Data Protection Regulation)

  • βœ… Article 25 - Privacy by design and default
  • βœ… Article 32 - Security of processing (encryption)
  • βœ… Article 33 - Breach notification (monitoring + alerts)
  • βœ… Article 35 - Data protection impact assessment (threat model)

HIPAA (Health Insurance Portability and Accountability Act)

  • ⚠️ Not HIPAA-certified - Additional BAA required for PHI
  • βœ… Technical safeguards in place (encryption, access controls)
  • βœ… Audit controls (comprehensive logging)

Compliance Reporting

Automated compliance reports available:
  • User access logs (who accessed what, when)
  • Form modification history (version control)
  • Submission exports (with audit trail)
  • Security event summary (failed logins, access denied)

🚨 Vulnerability Reporting

Responsible Disclosure Policy

We take security vulnerabilities seriously. If you discover a security issue: DO:
  • βœ… Report privately via GitHub Security Advisories
  • βœ… Provide detailed reproduction steps
  • βœ… Allow 90 days for remediation before public disclosure
  • βœ… Work with us to verify the fix
DON’T:
  • ❌ Publicly disclose before we’ve had a chance to fix
  • ❌ Exploit vulnerabilities beyond proof-of-concept
  • ❌ Access or modify other users’ data
  • ❌ Perform DOS/DDOS attacks

Reporting Channels

  1. GitHub Security Advisory (Preferred)
  2. Email: security@withunify.org (if GitHub unavailable)
    • Use PGP key: [Link to public key]
    • Include: Description, impact, reproduction steps

Response Timeline

SeverityInitial ResponseFix TimelineDisclosure
Critical24 hours7 daysAfter fix + 14 days
High48 hours30 daysAfter fix + 30 days
Medium5 days60 daysAfter fix + 60 days
Low10 days90 daysAfter fix + 90 days

Security Bounty

Currently no formal bug bounty program, but we recognize security researchers:
  • Public acknowledgment (with permission)
  • Swag/merchandise for significant findings
  • Potential monetary reward for critical vulnerabilities (case-by-case)

πŸ”§ Security Best Practices (For Developers)

Code Review Checklist

Before submitting a PR, verify:
  • Authentication: All server actions have auth guards
  • Authorization: Resource ownership verified (checkFormAccess, verifySubmissionAccess)
  • Input Validation: All user input validated (zod schemas)
  • Output Encoding: User-generated content sanitized (DOMPurify)
  • SQL Injection: Using Supabase client (no raw SQL strings)
  • XSS Prevention: No dangerouslySetInnerHTML without sanitization
  • Path Traversal: File paths sanitized (sanitizeStoragePath)
  • Secrets: No hardcoded API keys or passwords
  • Logging: No PII in log messages
  • Error Messages: Generic errors to users (details in logs)
  • Rate Limiting: Considered for new public endpoints
  • Audit Logging: Mutations logged via audit-logger.ts

Secure Coding Patterns

βœ… GOOD: Server Action with Auth

export async function updateForm(formId: string, data: FormData) {
  // 1. Auth guard
  const auth = await checkFormAccess(formId);
  if (!auth.success) return { success: false, error: auth.error };

  // 2. Input validation
  const validated = formSchema.safeParse(data);
  if (!validated.success) return { success: false, error: "Invalid input" };

  // 3. Database operation
  const { error } = await supabaseAdmin
    .from("forms")
    .update(validated.data)
    .eq("id", formId);

  // 4. Audit logging
  await logFormAudit("update", formId, auth.session.user.id, ...);

  return { success: true };
}

❌ BAD: Missing Auth / Validation

export async function updateForm(formId: string, data: any) {
  // NO auth check - anyone can update any form!
  // NO input validation - SQL injection risk!
  const { error } = await supabaseAdmin
    .from("forms")
    .update(data) // Unsafe!
    .eq("id", formId);

  return { success: !error };
}

Security Testing

Run security checks locally:
# Type safety
pnpm --dir apps/terra tsc --noEmit

# Linting (includes security rules)
pnpm --dir apps/terra lint

# Dependency vulnerabilities
npm audit

# Unit tests (includes security tests)
pnpm --dir apps/terra test

# E2E tests
pnpm --dir apps/terra test:e2e

πŸ“… Security Update Policy

  • Critical vulnerabilities: Patched within 7 days
  • High vulnerabilities: Patched within 30 days
  • Dependency updates: Monthly review, quarterly updates
  • Security audits: Quarterly internal review, annual external audit

πŸ“š Additional Resources


Last Updated: 2026-01-08 Security Contact: security@withunify.org Version: 1.0