Skip to content

Latest commit

 

History

History
108 lines (91 loc) · 3.86 KB

File metadata and controls

108 lines (91 loc) · 3.86 KB

Security Fix: API Key Isolation Between Users

Issue Description

A critical security vulnerability was discovered where API keys from one user account would persist in localStorage after logout, allowing the next user logging in on the same device to access the previous user's API keys. This affected all AI provider API keys stored in the application.

Root Cause

  1. Incomplete Logout Process: The logout flow only signed out from Convex but didn't clear sensitive localStorage data
  2. Persistent Encryption Keys: The master encryption key used to encrypt API keys persisted after logout
  3. No User Context Validation: API keys were stored without user-specific namespacing

Security Impact

  • High Severity: Complete access to previous user's AI provider API keys
  • Affected Data: OpenAI, Anthropic, Google, and other provider API keys
  • Attack Vector: Any subsequent user on the same device after logout

Fix Implementation

1. Enhanced SignOut Button (/src/SignOutButton.tsx)

  • Added comprehensive cleanup of all API keys (plain and encrypted)
  • Clear master encryption key and fingerprint
  • Remove all user preferences and legacy data
  • Pattern-based cleanup for any app-prefixed keys
// Clear all API keys for each provider
for (const providerId of Object.keys(AI_PROVIDERS)) {
  localStorage.removeItem(API_KEY_STORAGE_PREFIX + providerId);
  localStorage.removeItem(API_KEY_STORAGE_PREFIX + providerId + '_encrypted');
  localStorage.removeItem(API_KEY_STORAGE_PREFIX + providerId + '_encrypted_flag');
}

// Clear encryption keys
clearEncryptionKeys();

// Pattern-based cleanup
const keysToRemove = [];
for (let i = 0; i < localStorage.length; i++) {
  const key = localStorage.key(i);
  if (key && (key.startsWith('c3chat_') || key.startsWith('apiKey_'))) {
    keysToRemove.push(key);
  }
}

2. User Switch Detection (/src/App.tsx)

  • Track last logged-in user ID
  • Detect when a different user logs in
  • Automatically clear all sensitive data on user switch
  • Force page reload for clean state
useEffect(() => {
  if (loggedInUser && loggedInUser._id !== lastUserId) {
    if (lastUserId !== null) {
      // User switch detected - clear sensitive data
      const keysToRemove = [];
      // ... pattern matching for sensitive keys
      keysToRemove.forEach(key => localStorage.removeItem(key));
      window.location.reload();
    }
    setLastUserId(loggedInUser._id);
  }
}, [loggedInUser, lastUserId]);

3. Encryption Utility Enhancement (/src/lib/crypto-utils.ts)

  • Added clearEncryptionKeys() function
  • Removes master encryption key and fingerprint
  • Clears all encrypted data flags

Testing

Created comprehensive tests in /src/__tests__/security-api-key-isolation.test.tsx:

  • Verify complete cleanup on logout
  • Test user switch detection
  • Validate encryption key removal
  • Check legacy format handling

What Gets Cleared

  1. API Keys: All provider API keys (plain and encrypted)
  2. Encryption: Master key, fingerprint, encrypted flags
  3. Preferences: Provider and model selections
  4. Legacy Data: Any old format API keys

Verification Steps

  1. Login as User A and add API keys
  2. Logout using the Sign Out button
  3. Login as User B
  4. Verify no API keys are present
  5. Check browser console for cleanup logs

Future Recommendations

  1. Consider server-side API key storage for enhanced security
  2. Implement user-specific key namespacing
  3. Add periodic key rotation
  4. Monitor for unauthorized API key access

Deployment Notes

  • This fix requires no database changes
  • Browser refresh forced on user switch for clean state
  • Backwards compatible with existing encrypted keys
  • No user action required - automatic cleanup

Security Audit Trail

  • Discovered: June 19, 2025
  • Fixed: June 19, 2025
  • Severity: Critical
  • Type: Information Disclosure / Privilege Escalation
  • CVSS Score: 8.8 (High)