Skip to main content

Overview

SecurAtlas handles sensitive compliance data including security assessment results, evidence documents, integration credentials, and tenant configurations. Data protection is enforced at every layer.

Encryption at Rest

All data stored in Supabase is encrypted at rest using AES-256 encryption managed by the Supabase platform:

PostgreSQL Database

Encrypted at the storage layer via Supabase-managed disk encryption. Tenants cannot access raw disk data.

Supabase Storage

Evidence files, policy documents, and exports are encrypted at rest in Supabase Storage buckets.
Encryption at rest is managed entirely by Supabase infrastructure. SecurAtlas does not implement application-level encryption on database fields, with the exception of OAuth secrets stored in Supabase Vault.

Encryption in Transit

All data in transit is protected with TLS 1.2+:
ConnectionProtocol
Browser to VercelHTTPS (TLS 1.2+)
Vercel to SupabaseHTTPS (TLS 1.2+)
Edge Functions to Supabase DBTLS encrypted connection
Edge Functions to external APIsHTTPS (provider-enforced)
Supabase Dashboard accessHTTPS
Never configure local development to bypass TLS. Even locally, use the HTTPS Supabase project URL, not a direct unencrypted database connection.

OAuth Secret Management

Integration OAuth tokens (access tokens, refresh tokens) are stored using Supabase Vault, not in plain-text database columns.

How It Works

-- Store a secret in the vault
SELECT rpc_integration_set_secret(
  p_connection_id := 'uuid',
  p_secret_name   := 'access_token',
  p_secret_value  := 'oauth-token-value'
);
The function:
  1. Encrypts the value using pgsodium (Supabase’s encryption extension)
  2. Stores the encrypted value in vault.secrets
  3. Stores the vault secret ID in integration_connections.access_token_vault_id
To retrieve:
-- Retrieve a decrypted secret (only accessible to service role)
SELECT rpc_integration_get_secret(
  p_connection_id := 'uuid'
);
Vault secrets are only accessible via the service_role key. RLS-scoped clients cannot read vault contents, even if the user has access to the integration_connections table.

API Key Protection

ANTHROPIC_API_KEY

The Anthropic Claude API key is protected with multiple controls:
  • Stored as a Supabase Edge Function secret, not in the database
  • Only accessible from server-side code (Edge Functions, Server Actions)
  • Never included in NEXT_PUBLIC_ environment variables
  • Not transmitted to the client in any API response

SUPABASE_SERVICE_ROLE_KEY

The service role key bypasses RLS and has full database access:
  • Used only in webhooks, cron handlers, and admin operations
  • Accessed via getSupabaseServerAdminClient() which is server-only
  • Never exposed in client bundles or API responses

Logging and PII

  • No PII (emails, names, tokens) in application logs
  • console.log statements are audited to prevent accidental PII leakage
  • Supabase Edge Function logs do not include request bodies by default
  • Error messages sent to the client are generic; detailed errors go to server logs only

Storage Bucket Security

Evidence and policy document buckets are configured with:
SettingValue
Public accessDisabled
RLSEnabled (tenant-scoped)
File size limit50 MB
Allowed MIME typesPDF, PNG, JPG, DOCX, XLSX, CSV
-- Example storage RLS policy
CREATE POLICY "Tenant members can read their evidence"
  ON storage.objects FOR SELECT
  USING (
    bucket_id = 'evidence'
    AND (storage.foldername(name))[1] IN (
      SELECT tenant_id::text FROM tenant_memberships
      WHERE user_id = auth.uid()
    )
  );
Evidence files are organized by tenant ID in storage paths (evidence/{tenant_id}/filename). This structure enables simple RLS policies based on folder names.