Skip to content

[WIP] Remove passwordHash from frontend User type for security - #11

Merged
aimenng merged 2 commits into
mainfrom
copilot/remove-password-hash-field
Feb 12, 2026
Merged

[WIP] Remove passwordHash from frontend User type for security#11
aimenng merged 2 commits into
mainfrom
copilot/remove-password-hash-field

Conversation

Copilot AI commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

Security and Code Quality Fixes Plan

  • 1. Security: Remove passwordHash field from User interface in types.ts
  • 2. Security: Remove GEMINI_API_KEY injection from vite.config.ts define block
  • 3. Code Quality: Remove unused chunkItems function from context.tsx
  • 4. Code Quality: Fix stale closure in authContext.tsx by wrapping resetAuthState in useCallback
  • 5. Code Style: Remove trailing blank lines (7 lines) from context.tsx
  • 6. Code Style: Move import statement to top of utils/aiService.ts
  • 7. Verify build and TypeScript check
  • 8. Run code review
  • 9. Run CodeQL security scan
  • 10. Final verification and completion
Original prompt

Overview

This PR addresses security vulnerabilities, code quality issues, and optimization opportunities discovered during a comprehensive code audit. All changes are carefully scoped to avoid breaking existing functionality.

Changes Required

1. 🔒 Security: Remove passwordHash from frontend User type (types.ts)

The User interface in types.ts line 15 currently exposes passwordHash as an optional field. Even though the backend likely strips it before sending, having it in the frontend type is a security anti-pattern and signals that server-only data might leak.

Fix: Remove the passwordHash field from the frontend User interface. Add a comment noting that the full user model lives on the backend.

Current code (line 12-24):

export interface User {
  id: string;
  email: string;
  passwordHash?: string; // Never store plain password in frontend
  invitationCode: string;
  boundInvitationCode?: string;
  emailVerified?: boolean;
  createdAt: string;
  name?: string;
  avatar?: string;
  gender?: 'male' | 'female';
  partnerId?: string | null;
}

Should become:

export interface User {
  id: string;
  email: string;
  // NOTE: passwordHash is intentionally excluded from frontend types — it only exists on the backend model.
  invitationCode: string;
  boundInvitationCode?: string;
  emailVerified?: boolean;
  createdAt: string;
  name?: string;
  avatar?: string;
  gender?: 'male' | 'female';
  partnerId?: string | null;
}

2. 🔒 Security: Remove GEMINI_API_KEY injection from Vite config (vite.config.ts)

vite.config.ts lines 19-22 currently inject GEMINI_API_KEY into the frontend JavaScript bundle via define. This means anyone can extract the API key from the browser devtools or the built JS files.

Current code (lines 19-22):

define: {
    'process.env.API_KEY': JSON.stringify(env.GEMINI_API_KEY),
    'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY)
},

Fix: Remove the entire define block. The AI service (utils/aiService.ts) already uses its own API key mechanism via localStorage (for the Doubao API), and GEMINI_API_KEY is not actually referenced anywhere in the frontend source code via process.env.GEMINI_API_KEY or process.env.API_KEY. Search the codebase to confirm — if there are references, they should be moved to use the backend proxy pattern instead, but from my audit they don't exist.

The resulting vite.config.ts should be:

import path from 'path';
import { defineConfig, loadEnv } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig(({ mode }) => {
    const env = loadEnv(mode, '.', '');
    return {
      server: {
        port: 3000,
        host: '0.0.0.0',
        proxy: {
          '/api': {
            target: env.VITE_BACKEND_URL || 'http://localhost:8787',
            changeOrigin: true,
          },
        },
      },
      plugins: [react()],
      resolve: {
        alias: {
          '@': path.resolve(__dirname, '.'),
        }
      }
    };
});

3. 🔧 Code Quality: Fix chunkItems dead code in context.tsx

The function chunkItems (lines 170-177 in context.tsx) is defined but never used anywhere in the file or the project. The file uses buildAdaptiveMemoryChunks instead.

Fix: Remove the chunkItems function entirely from context.tsx.

Remove these lines:

const chunkItems = <T,>(items: T[], size: number): T[][] => {
  if (size <= 0) return [items];
  const chunks: T[][] = [];
  for (let i = 0; i < items.length; i += size) {
    chunks.push(items.slice(i, i + size));
  }
  return chunks;
};

4. 🔧 Code Quality: Fix stale closure in authContext.tsx

In authContext.tsx, refreshAuthData (line 88) is wrapped with useCallback(…, []) but internally calls resetAuthState() which is a plain function referencing state setters. While the React setState functions themselves are stable, the resetAuthState function should be wrapped in useCallback to make the dependency intent explicit and avoid future refactoring bugs.

Fix: Wrap resetAuthState in useCallback:

Change:

const resetAuthState = () => {
    setCurrentUser(null);
    setPartner(null);
    setUsers([]);
    setAllNotifications([]);
    cancelCloudWarmup();
    clearFocusStatsCache();
    clearPeriodTrackerCache();
};

To:

const resetAuthState = useCallback(() => {
    setCurrentUser(null);
    setPartner(null);
    setUsers([]);
    setAllNotifications([]);
    cancelCloudWarmup();
    clearFocusStatsCache();
    clearPeriodTrackerCache();
}, []);

Then add resetAuthState to the dependency array of refreshAuthData:

const refreshAuthData = useCallback(async () => {
    // ... existing code ...
}, [resetAuthState]);

5. 🔧 Code Quality: Remove trailing blank lines in context.tsx

context.tsx has 7 trailing blank lines (lines 687-694) at the e...

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel

vercel Bot commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
gifts-couple-connection Ready Ready Preview, Comment Feb 12, 2026 2:22pm

… unused code, and fix closures

Co-authored-by: aimenng <141473804+aimenng@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@aimenng
aimenng marked this pull request as ready for review February 12, 2026 14:22
@aimenng
aimenng merged commit d2736c8 into main Feb 12, 2026
3 checks passed
Copilot stopped work on behalf of aimenng due to an error February 12, 2026 14:23
Copilot AI requested a review from aimenng February 12, 2026 14:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants