Skip to content

Bug: Shared encryption key across all tenants exposes all users on single key compromise #14

@FuturMix

Description

@FuturMix

Description

All users share a single SETTINGS_ENCRYPTION_KEY environment variable to encrypt/decrypt their API keys and secrets. The GET /api/settings/crypto-key endpoint returns this same key to every authenticated user.

If any single user's key is compromised, or the environment variable leaks, all users' encrypted secrets can be decrypted.

Location

  • apps/web/src/lib/server-crypto.ts — single shared key for all encrypt/decrypt operations
  • apps/web/src/app/api/settings/crypto-key/route.ts — returns the same key to every user

Impact

  • Severity: HIGH (design-level)
  • Single point of failure: one key compromise affects all users
  • Violates multi-tenant isolation guarantees
  • Circumvents per-user RLS protections in the database

Suggested Fix

Derive per-user encryption keys from the master key + user ID:

import { createHmac } from 'crypto';

function deriveUserKey(masterKey: Buffer, userId: string): Buffer {
  return createHmac('sha256', masterKey)
    .update(userId)
    .digest();
}

This ensures each user's data is encrypted with a unique key while only requiring one master secret in the environment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions