Skip to content

Clean up security leak, dependency categorization, and file encoding - #12

Merged
aimenng merged 2 commits into
mainfrom
copilot/fix-backend-mapper-security
Feb 12, 2026
Merged

Clean up security leak, dependency categorization, and file encoding#12
aimenng merged 2 commits into
mainfrom
copilot/fix-backend-mapper-security

Conversation

Copilot AI commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

Addresses residual issues from previous security audit: API response leaks, dependency miscategorization, package manager conflicts, and file encoding inconsistencies.

Changes

Security

  • Remove passwordHash field from mapUser API responses (was returning empty string, field shouldn't exist)

Dependencies

  • Move @capacitor/cli to devDependencies (build tool, not runtime)
  • Delete pnpm-lock.yaml (standardize on npm, eliminates lockfile conflicts)

File encoding

  • Strip BOM from backend/src/routes/{app,auth}Routes.js (UTF-8 doesn't need it)

Documentation

  • Add JSDoc to isEmailTaken clarifying it's local-only (checks loaded users, not backend-wide)
// Before: backend/src/mappers.js
export const mapUser = (row) => ({
  id: row.id,
  email: row.email,
  passwordHash: '',  // ⚠️ shouldn't be in API response
  // ...
});

// After
export const mapUser = (row) => ({
  id: row.id,
  email: row.email,
  // passwordHash removed entirely
  // ...
});

Note: Backend dependencies remain in root package.json as required by Vercel serverless function (api/index.jsbackend/src/app.js).

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • registry.npmmirror.com
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/_temp/ghcca-node/node/bin/npm install ction (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/_temp/ghcca-node/node/bin/npm install --legacy-peer-deps (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

综合修复 PR — 第二批:依赖分离、后端 mapper 安全、lockfile 统一、isEmailTaken 改善

本 PR 修复前一个 PR(安全修复/死代码清理)未涵盖的剩余问题。所有改动保持向后兼容,不影响现有功能。

⚠️ 重要约束:

  • 不删除任何分支 — 用户需要保留所有分支审视开发进程
  • 所有改动必须向后兼容,不破坏现有部署功能
  • 不新增依赖包

修复 1: 后端 mappers.js 中 mapUser 仍然返回 passwordHash: ''

文件: backend/src/mappers.js

问题: 后端 mapUser 函数在第 7 行返回 passwordHash: ''。虽然值为空字符串,但这个字段不应该出现在 API 响应中。前端类型定义如果移除了 passwordHash(由 PR#1 处理),那后端也不应该再发送这个字段。

修复: 移除 mapUser 返回对象中的 passwordHash: '' 这一行。

当前代码 (lines 1-17):

export const mapUser = (row) => {
  if (!row) return null;

  return {
    id: row.id,
    email: row.email,
    passwordHash: '',
    invitationCode: row.invitation_code || '',
    boundInvitationCode: row.bound_invitation_code || '',
    emailVerified: Boolean(row.email_verified),
    createdAt: row.created_at,
    name: row.name || '',
    avatar: row.avatar || '',
    gender: row.gender || 'male',
    partnerId: row.partner_id || null,
  };
};

修改为:

export const mapUser = (row) => {
  if (!row) return null;

  return {
    id: row.id,
    email: row.email,
    invitationCode: row.invitation_code || '',
    boundInvitationCode: row.bound_invitation_code || '',
    emailVerified: Boolean(row.email_verified),
    createdAt: row.created_at,
    name: row.name || '',
    avatar: row.avatar || '',
    gender: row.gender || 'male',
    partnerId: row.partner_id || null,
  };
};

修复 2: 根 package.json 混入了后端专属依赖

文件: package.json (root)

问题:package.jsondependencies 中同时包含了前端依赖(react, lucide-react, @vercel/*)和后端专属依赖(bcryptjs, compression, cors, express, express-rate-limit, jsonwebtoken, nodemailer, dotenv)。后端已经有自己独立的 backend/package.json 列出了所有这些依赖。

根目录混入后端依赖会导致:

  • Vercel 部署时安装不必要的包
  • 前端 bundle 有可能错误地引入后端库
  • npm install / pnpm install 在根目录安装过多包

修复: 从根 package.jsondependencies 中移除以下仅后端使用的包(它们已在 backend/package.json 中声明):

  • bcryptjs
  • compression
  • cors
  • express
  • express-rate-limit
  • jsonwebtoken
  • nodemailer
  • dotenv

但是注意:由于 Vercel serverless functions 通过 api/index.jsbackend/src/app.js 引用后端代码,Vercel 在部署 serverless function 时需要从根目录的 node_modules 找到这些依赖。所以我们不能直接移除它们。

替代方案(安全做法): 在根 package.json 中添加注释说明这些依赖是被 api/index.js serverless function 使用的,并将 @capacitor/clidependencies 移到 devDependencies(因为 CLI 工具是开发时才用的,不应该出现在生产 dependencies 中)。

修改根 package.json:

{
  "name": "gifts---couple-connection",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "dev:frontend": "vite",
    "dev:backend": "node backend/src/index.js",
    "dev:full": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"",
    "migrate:images": "node backend/scripts/migrateInlineMemoriesToStorage.js",
    "start:backend": "node backend/src/index.js",
    "build": "vite build",
    "preview": "vite preview",
    "check:text-encoding": "node scripts/check-text-encoding.mjs",
    "build:mobile": "npm run build && npx cap sync android",
    "android:sync": "npx cap sync android",
    "android:open": "npx cap open android",
    "android:apk": "npm run build:mobile && bash scripts/bootstrap-gradle-wrapper.sh && cd android && ./gradlew assembleDebug",
    "android:sdk:setup": "bash scripts/setup-android-sdk.sh",
    "android:keystore:create": "bash scripts/create-android-keystore.sh",
    "android:apk:release": "npm run build:mobile && bash scripts/bootstrap-gradle-wrapper.sh && cd android && ./gradlew assembleOfficialRelease",
    "android:bundle:release": "npm run build:mobile && bash scripts/bootstrap-gradle-wrapper.sh && cd android && ./gradlew bundleOfficialRelease"
  },
  "dependencies": {
    "@capacitor/android": "^8.1.0",
    "@capacitor/core": "^8.1.0",
    "@supabase/supabase-js": "^2.95.3",
    "@vercel/analytics": "^1.6.1",
    "@vercel/speed-insights": "^1.3.1",
    "bcryptjs": "^3.0.3",
    "compression": "^1.8.1",
    "concurrently": "^9.2.1",
    "cors": "^2.8.6",
    "dayjs": "^1.11.19",
    "dotenv": "^17.2.4",
    "express": "^5.2.1",
    "express-rate-limit": "^7.5.1",
    "jsonwebtoken": "^9.0.3",
    "lucide-react": "^0.563.0",
    "nodemailer": "^8.0.1",
    "react": "^19.2.4",
    "react-dom": "^19.2.4"
  },
  "devDependencies": {
    "@capacitor/cli": "^7.5.0",
    "@types/node": "^22.14.0",
    "@types/react": "^19.0.0",
    "@types/react-dom": "^19.0.0",
    "@vitejs/plugin-react": "^5.0.0",
    "typescript": "~5.8.2",
    "vite": "^6.2.0"
  }
}

Key change: move @capacitor/cli from dependencies to devDependencies because it's a development-time CLI tool.


修复 3: 删除多余的 pnpm-lock.yaml,统一使用 npm 作为包管理器

文件: 删除 pnpm-lock.yaml

问题: 仓库同时存在 package-lock.json(npm)和 pnpm-lock.yaml(pnpm),导致:

由于 Vercel 默认使用 npm,且仓库的 scripts 都使用 npm run,应统一使用 npm。

修复: 删除 pnpm-lock.yaml 文件。保留 package-lock.json


修复 4: 改善 isEmailTaken 函数的注释说...

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@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:32pm

…delete pnpm-lock, add JSDoc, remove BOM

Co-authored-by: aimenng <141473804+aimenng@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix passwordHash return in mapUser function Clean up security leak, dependency categorization, and file encoding Feb 12, 2026
Copilot AI requested a review from aimenng February 12, 2026 14:38
@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:44
@aimenng
aimenng merged commit ef4d1d1 into main Feb 12, 2026
3 checks passed
@aimenng

aimenng commented Feb 12, 2026

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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