Skip to content

Commit 9603ce2

Browse files
committed
fix: update dependencies and fix compatibility issues
- Update security audit documentation to recommend bun audit instead of npm audit - Update dependencies to latest versions (Zod 4.x, Express 5.x, and others) - Fix Zod 4.x breaking changes: - Replace error.errors with error.issues in auth route - Update z.record() API to require key and value schemas - Update uuid validation to use z.uuid() for direct UUID validation - Fix Express 5.x compatibility issues: - Add type assertion for passport.initialize() middleware - Replace app.get('*') with app.use() for 404 handler - Run security audit and fix vulnerabilities (reduced from 10 to 2 moderate issues)
1 parent 7c32426 commit 9603ce2

7 files changed

Lines changed: 689 additions & 609 deletions

File tree

doc/develop/SECURITY-AUDIT.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ username: z
517517
518518
---
519519
520-
### 3.4 缺少安全响应头
520+
### 3.4 缺少安全响应头(可以忽略)
521521
522522
**问题描述**:
523523
没有设置重要的安全响应头,如:
@@ -539,9 +539,12 @@ username: z
539539
540540
**建议**:
541541
542-
1. 定期运行 `npm audit` 检查依赖漏洞
543-
2. 使用 `npm audit fix` 修复已知漏洞
544-
3. 考虑使用 Snyk 或 Dependabot 进行持续监控
542+
1. 定期运行 `bun audit` 检查依赖漏洞(Bun 内置安全审计功能,推荐使用)
543+
2. 使用 `bun update` 更新所有依赖到最新兼容版本,或使用 `bun update --latest` 更新到最新版本(包括破坏性更新)
544+
3. 考虑使用 Snyk 或 Dependabot 进行持续监控和自动更新
545+
4. 定期检查依赖包的更新日志和安全公告
546+
547+
**注意**: 由于项目使用 `bun.lock` 作为锁文件,`npm audit` 无法直接使用(需要 `package-lock.json`)。建议统一使用 `bun audit` 进行安全审计。
545548
546549
### 4.2 环境变量管理
547550

server/bun.lock

Lines changed: 583 additions & 507 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/package.json

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,40 +21,40 @@
2121
"author": "rabithua",
2222
"license": "ISC",
2323
"dependencies": {
24-
"@aws-sdk/client-s3": "^3.484.0",
25-
"@aws-sdk/s3-request-presigner": "^3.484.0",
26-
"@prisma/client": "^6.10.1",
27-
"@types/cors": "^2.8.17",
28-
"@types/express": "^4.17.21",
29-
"@types/formidable": "^3.4.5",
30-
"@types/node": "^20.9.1",
31-
"@types/passport": "^1.0.16",
24+
"@aws-sdk/client-s3": "^3.932.0",
25+
"@aws-sdk/s3-request-presigner": "^3.932.0",
26+
"@prisma/client": "^6.19.0",
27+
"@types/cors": "^2.8.19",
28+
"@types/express": "^5.0.5",
29+
"@types/formidable": "^3.4.6",
30+
"@types/node": "^24.10.1",
31+
"@types/passport": "^1.0.17",
3232
"@types/passport-local": "^1.0.38",
33-
"@types/web-push": "^3.6.3",
34-
"aws-sdk": "^2.1528.0",
35-
"body-parser": "^1.20.2",
33+
"@types/web-push": "^3.6.4",
34+
"aws-sdk": "^2.1692.0",
35+
"body-parser": "^2.2.0",
3636
"cors": "^2.8.5",
37-
"eslint": "^8.56.0",
38-
"express": "^4.18.2",
39-
"feed": "^5.0.1",
40-
"formidable": "^3.5.1",
41-
"jose": "^6.0.11",
42-
"moment": "^2.29.4",
37+
"eslint": "^9.39.1",
38+
"express": "^5.1.0",
39+
"feed": "^5.1.0",
40+
"formidable": "^3.5.4",
41+
"jose": "^6.1.1",
42+
"moment": "^2.30.1",
4343
"passport": "^0.7.0",
4444
"passport-local": "^1.0.0",
45-
"rate-limiter-flexible": "^4.0.1",
46-
"sharp": "^0.32.6",
47-
"web-push": "^3.6.6",
48-
"zod": "^3.23.8"
45+
"rate-limiter-flexible": "^8.2.1",
46+
"sharp": "^0.34.5",
47+
"web-push": "^3.6.7",
48+
"zod": "^4.1.12"
4949
},
5050
"devDependencies": {
51-
"@antfu/eslint-config": "^2.6.3",
52-
"axios": "^1.7.7",
53-
"dotenv": "^16.5.0",
54-
"nodemon": "^3.0.1",
55-
"prettier": "^3.5.3",
56-
"prisma": "^6.10.1",
51+
"@antfu/eslint-config": "^6.2.0",
52+
"axios": "^1.13.2",
53+
"dotenv": "^17.2.3",
54+
"nodemon": "^3.1.11",
55+
"prettier": "^3.6.2",
56+
"prisma": "^6.19.0",
5757
"ts-node": "^10.9.2",
58-
"typescript": "^5.3.0"
58+
"typescript": "^5.9.3"
5959
}
6060
}

server/route/v2/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ authRouter.put(
8484

8585
const zodData = passwordChangeZod.safeParse(req.body);
8686
if (zodData.success === false) {
87-
throw new Error(zodData.error.errors[0].message);
87+
throw new Error(zodData.error.issues[0].message);
8888
}
8989

9090
const updatedUser = await changeUserPassword(oldpassword, newpassword, user.id);

server/server.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ app.use(injectDynamicUrls);
3232
app.use(rateLimiterMiddleware);
3333

3434
// Initialize Passport
35-
app.use(passport.initialize());
35+
app.use(passport.initialize() as unknown as express.RequestHandler);
3636

3737
// body parser
3838
app.use(
@@ -115,7 +115,8 @@ app.use('/v2/api', routerV2); // RESTful API
115115
// Global error handler (must be after all routes)
116116
app.use(errorHandler);
117117

118-
app.get('*', (req, res) => {
118+
// 404 handler - Express 5.x requires explicit path pattern
119+
app.use((req, res) => {
119120
res.status(404).send({
120121
code: 1,
121122
message: 'Api not found!',

server/utils/zod.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ export const SearchKeywordZod = z.object({
8282
// 反应相关验证
8383
export const ReactionCreateZod = z.object({
8484
type: z.string().min(1, '反应类型不能为空').max(50, '反应类型不能超过 50 个字符'), // emoji 通常很短,但留一些余量
85-
roteid: z.string().uuid('无效的笔记 ID'),
85+
roteid: z.uuid('无效的笔记 ID'),
8686
visitorId: z.string().max(200, '访客 ID 不能超过 200 个字符').optional(),
87-
visitorInfo: z.record(z.any()).optional(),
88-
metadata: z.record(z.any()).optional(),
87+
visitorInfo: z.record(z.string(), z.any()).optional(),
88+
metadata: z.record(z.string(), z.any()).optional(),
8989
});
9090

9191
// 附件文件名验证

web/package.json

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -14,90 +14,90 @@
1414
"@dnd-kit/core": "^6.3.1",
1515
"@dnd-kit/sortable": "^10.0.0",
1616
"@dnd-kit/utilities": "^3.2.2",
17-
"@dr.pogodin/react-helmet": "^3.0.2",
18-
"@radix-ui/react-avatar": "^1.1.10",
19-
"@radix-ui/react-checkbox": "^1.3.2",
20-
"@radix-ui/react-dialog": "^1.1.14",
21-
"@radix-ui/react-dropdown-menu": "^2.1.15",
22-
"@radix-ui/react-label": "^2.1.7",
23-
"@radix-ui/react-popover": "^1.1.14",
24-
"@radix-ui/react-scroll-area": "^1.2.9",
25-
"@radix-ui/react-select": "^2.2.5",
26-
"@radix-ui/react-slot": "^1.2.3",
27-
"@radix-ui/react-switch": "^1.2.5",
17+
"@dr.pogodin/react-helmet": "^3.0.4",
18+
"@radix-ui/react-avatar": "^1.1.11",
19+
"@radix-ui/react-checkbox": "^1.3.3",
20+
"@radix-ui/react-dialog": "^1.1.15",
21+
"@radix-ui/react-dropdown-menu": "^2.1.16",
22+
"@radix-ui/react-label": "^2.1.8",
23+
"@radix-ui/react-popover": "^1.1.15",
24+
"@radix-ui/react-scroll-area": "^1.2.10",
25+
"@radix-ui/react-select": "^2.2.6",
26+
"@radix-ui/react-slot": "^1.2.4",
27+
"@radix-ui/react-switch": "^1.2.6",
2828
"@radix-ui/react-tabs": "^1.1.13",
29-
"@radix-ui/react-toggle": "^1.1.9",
30-
"@radix-ui/react-toggle-group": "^1.1.10",
31-
"@radix-ui/react-tooltip": "^1.2.7",
29+
"@radix-ui/react-toggle": "^1.1.10",
30+
"@radix-ui/react-toggle-group": "^1.1.11",
31+
"@radix-ui/react-tooltip": "^1.2.8",
3232
"@tailwindcss/aspect-ratio": "^0.4.2",
33-
"@tailwindcss/typography": "^0.5.16",
34-
"@tailwindcss/vite": "^4.1.7",
33+
"@tailwindcss/typography": "^0.5.19",
34+
"@tailwindcss/vite": "^4.1.17",
3535
"@types/file-saver": "^2.0.7",
36-
"@types/lodash": "^4.17.17",
36+
"@types/lodash": "^4.17.20",
3737
"@types/react-avatar-editor": "^13.0.4",
38-
"@zumer/snapdom": "^1.7.1",
39-
"axios": "^1.9.0",
38+
"@zumer/snapdom": "^1.9.14",
39+
"axios": "^1.13.2",
4040
"browser-image-compression": "^2.0.2",
4141
"class-variance-authority": "^0.7.1",
4242
"clsx": "^2.1.1",
4343
"cmdk": "^1.1.1",
4444
"file-saver": "^2.0.5",
45-
"i18next": "^25.2.0",
46-
"isbot": "^5.1.27",
47-
"jotai": "^2.12.4",
45+
"i18next": "^25.6.2",
46+
"isbot": "^5.1.32",
47+
"jotai": "^2.15.1",
4848
"jwt-decode": "^4.0.0",
49-
"linkify-react": "^4.3.1",
50-
"linkifyjs": "^4.3.1",
49+
"linkify-react": "^4.3.2",
50+
"linkifyjs": "^4.3.2",
5151
"lodash": "^4.17.21",
52-
"lucide-react": "^0.511.0",
52+
"lucide-react": "^0.553.0",
5353
"mobile-detect": "^1.4.5",
5454
"moment": "^2.30.1",
55-
"motion": "^12.15.0",
55+
"motion": "^12.23.24",
5656
"next-themes": "^0.4.6",
57-
"radix-ui": "^1.4.2",
58-
"react": "^19.1.0",
59-
"react-dom": "^19.1.0",
60-
"react-easy-crop": "^5.4.2",
61-
"react-i18next": "^15.5.3",
62-
"react-intersection-observer": "^9.16.0",
57+
"radix-ui": "^1.4.3",
58+
"react": "^19.2.0",
59+
"react-dom": "^19.2.0",
60+
"react-easy-crop": "^5.5.3",
61+
"react-i18next": "^16.3.3",
62+
"react-intersection-observer": "^10.0.0",
6363
"react-photo-view": "^1.2.7",
64-
"react-qr-code": "^2.0.17",
65-
"react-router": "^7.5.3",
66-
"react-router-dom": "^7.6.0",
64+
"react-qr-code": "^2.0.18",
65+
"react-router": "^7.9.6",
66+
"react-router-dom": "^7.9.6",
6767
"react-use-measure": "^2.1.7",
68-
"sonner": "^2.0.5",
69-
"swr": "^2.3.3",
70-
"tailwind-merge": "^3.3.0",
71-
"tailwindcss": "^4.1.7",
68+
"sonner": "^2.0.7",
69+
"swr": "^2.3.6",
70+
"tailwind-merge": "^3.4.0",
71+
"tailwindcss": "^4.1.17",
7272
"vaul": "^1.1.2",
73-
"zod": "^3.25.28"
73+
"zod": "^4.1.12"
7474
},
7575
"devDependencies": {
76-
"@eslint/js": "^9.25.0",
77-
"@types/node": "^22.15.21",
78-
"@types/react": "^19.1.2",
79-
"@types/react-dom": "^19.1.2",
80-
"@typescript-eslint/eslint-plugin": "^8.32.1",
81-
"@typescript-eslint/parser": "^8.32.1",
82-
"@vitejs/plugin-react-swc": "^3.9.0",
83-
"cross-env": "^7.0.3",
84-
"dotenv": "^16.5.0",
85-
"eslint": "^9.25.0",
86-
"eslint-config-prettier": "^10.1.5",
87-
"eslint-plugin-prettier": "^5.4.0",
76+
"@eslint/js": "^9.39.1",
77+
"@types/node": "^24.10.1",
78+
"@types/react": "^19.2.5",
79+
"@types/react-dom": "^19.2.3",
80+
"@typescript-eslint/eslint-plugin": "^8.46.4",
81+
"@typescript-eslint/parser": "^8.46.4",
82+
"@vitejs/plugin-react-swc": "^4.2.2",
83+
"cross-env": "^10.1.0",
84+
"dotenv": "^17.2.3",
85+
"eslint": "^9.39.1",
86+
"eslint-config-prettier": "^10.1.8",
87+
"eslint-plugin-prettier": "^5.5.4",
8888
"eslint-plugin-react": "^7.37.5",
89-
"eslint-plugin-react-hooks": "^5.2.0",
90-
"eslint-plugin-react-refresh": "^0.4.19",
91-
"eslint-plugin-react-you-might-not-need-an-effect": "^0.0.39",
92-
"eslint-plugin-tailwindcss": "^3.18.0",
93-
"globals": "^16.0.0",
94-
"prettier": "^3.5.3",
95-
"prettier-plugin-tailwindcss": "^0.6.11",
96-
"tw-animate-css": "^1.3.0",
97-
"typescript": "~5.8.3",
98-
"typescript-eslint": "^8.30.1",
99-
"vite": "^6.3.5",
100-
"vite-plugin-pwa": "^1.0.3",
89+
"eslint-plugin-react-hooks": "^7.0.1",
90+
"eslint-plugin-react-refresh": "^0.4.24",
91+
"eslint-plugin-react-you-might-not-need-an-effect": "^0.7.0",
92+
"eslint-plugin-tailwindcss": "^3.18.2",
93+
"globals": "^16.5.0",
94+
"prettier": "^3.6.2",
95+
"prettier-plugin-tailwindcss": "^0.7.1",
96+
"tw-animate-css": "^1.4.0",
97+
"typescript": "~5.9.3",
98+
"typescript-eslint": "^8.46.4",
99+
"vite": "^7.2.2",
100+
"vite-plugin-pwa": "^1.1.0",
101101
"vite-tsconfig-paths": "^5.1.4",
102102
"workbox-window": "^7.3.0"
103103
}

0 commit comments

Comments
 (0)