- Complete security audit of backend encryption architecture - Document KEK-DEK user-level encryption implementation - Analyze database backup/restore and import/export mechanisms - Identify critical missing import/export functionality - Confirm dual-layer encryption (field + file level) implementation - Validate session management and authentication flows Key findings: ✅ Excellent KEK-DEK architecture with true multi-user data isolation ✅ Correct removal of hardware fingerprint dependencies ✅ Memory database + dual encryption + periodic persistence ❌ Import/export endpoints completely disabled (503 status) ⚠️ OIDC client_secret not encrypted in storage Overall security grade: B+ (pragmatic implementation with good taste) Immediate priority: Restore import/export functionality for data migration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
5.8 KiB
5.8 KiB
TERMIX 后端安全架构审计报告
审计日期: 2025-01-22 审计人: Security Review (Linus-style Analysis) 项目版本: V2 KEK-DEK 架构
执行摘要
🟢 总体评分: B+ (好品味的实用主义实现)
这是一个展现"好品味"设计思维的安全架构实现。项目团队正确地删除了过度设计的复杂性,实现了真正的多用户数据隔离,体现了 Linus "删除代码比写代码更重要" 的哲学。
核心优势
- ✅ KEK-DEK 架构正确实现,真正的多用户数据隔离
- ✅ 删除硬件指纹等容器化时代的过时依赖
- ✅ 内存数据库 + 双层加密 + 周期性持久化的优秀架构
- ✅ 简洁的会话管理,合理的用户体验平衡
关键缺陷
- ❌ 导入导出功能完全被禁用 (503状态),严重影响数据迁移
- ⚠️ OIDC client_secret 未加密存储
- ⚠️ 生产环境CORS配置过于宽松
详细分析
1. 加密架构 (评分: A-)
KEK-DEK 实现
用户密码 → KEK (PBKDF2) → DEK (AES-256-GCM) → 字段加密
优势:
- KEK 从不存储,每次从密码推导
- DEK 加密存储,运行时内存缓存
- 每用户独立加密空间
- 没有"全局主密钥"单点失败
会话管理:
- 2小时会话超时(合理的用户体验)
- 30分钟不活跃超时(不是1分钟的极端主义)
- DEK直接缓存(删除了just-in-time推导的用户体验灾难)
2. 数据库架构 (评分: A)
双层保护策略
┌─────────────────────────────────────┐
│ 内存数据库 (better-sqlite3 :memory:) │ ← 运行时数据
├─────────────────────────────────────┤
│ 双层加密保护 │
│ └─ 字段级:KEK-DEK (用户数据) │ ← 数据安全
│ └─ 文件级:AES-256-GCM (整个DB) │ ← 存储安全
├─────────────────────────────────────┤
│ 加密文件:db.sqlite.encrypted │ ← 持久化存储
└─────────────────────────────────────┘
架构优势:
- 内存数据库:极高读写性能
- 每5分钟自动持久化:性能与安全平衡
- 文件级AES-256-GCM加密:静态数据保护
- 容器化友好:删除硬件指纹依赖
3. 系统密钥管理 (评分: B+)
JWT密钥保护
// 正确的系统级加密实现
private static getSystemMasterKey(): Buffer {
const envKey = process.env.SYSTEM_MASTER_KEY;
if (envKey && envKey.length >= 32) {
return Buffer.from(envKey, 'hex');
}
// 开发环境有明确警告
databaseLogger.warn("Using default system master key - NOT SECURE FOR PRODUCTION");
}
优势:
- JWT密钥加密存储(不是base64编码)
- 环境变量配置支持
- 开发环境有明确安全警告
4. 权限与会话管理 (评分: A-)
中间件分层
const authenticateJWT = authManager.createAuthMiddleware(); // JWT验证
const requireDataAccess = authManager.createDataAccessMiddleware(); // 数据访问
设计优势:
- 分离JWT验证和数据访问权限
- 清晰的职责边界
- 423状态码正确表示数据锁定状态
严重问题
1. 导入导出功能缺失 (严重程度: 高)
当前状态:
app.post("/database/export", async (req, res) => {
res.status(503).json({
error: "Database export temporarily disabled during V2 security upgrade"
});
});
影响:
- 用户无法迁移数据到新实例
- 无法进行选择性数据备份
- 系统维护和升级困难
2. OIDC配置安全 (严重程度: 中)
问题:
// client_secret 明文存储在settings表
const config = {
client_id,
client_secret, // 应该加密存储
issuer_url,
// ...
};
立即修复建议
1. 重新实现导入导出功能
// 建议的API设计
POST /database/export {
"password": "user_password", // 解密用户数据
"scope": "user_data", // user_data | system_config
"format": "encrypted" // encrypted | plaintext
}
2. 加密OIDC配置
// 存储前加密敏感字段
const encryptedConfig = DataCrypto.encryptRecordForUser("settings", config, adminUserId);
3. 生产环境安全加强
// 启动时验证关键环境变量
if (process.env.NODE_ENV === 'production') {
if (!process.env.SYSTEM_MASTER_KEY) {
throw new Error("SYSTEM_MASTER_KEY required in production");
}
}
技术债务评估
已正确删除的复杂性
- ✅ 硬件指纹依赖(容器化时代过时)
- ✅ Just-in-time密钥推导(用户体验灾难)
- ✅ Migration-on-access逻辑(过度设计)
- ✅ Legacy data兼容性检查(维护噩梦)
保留的合理简化
- ✅ 固定系统密钥种子(实用性优于理论安全)
- ✅ 2小时会话超时(用户体验与安全平衡)
- ✅ 内存数据库选择(性能优先)
最终评价
这个安全架构体现了真正的工程智慧:
- 选择了可工作的实用方案而非理论完美
- 正确地删除了过度设计的复杂性
- 实现了真正的多用户数据隔离
- 平衡了安全性与用户体验
关键优势: 这是难得的"好品味"安全实现,删除了大多数项目的过度设计垃圾。
主要风险: 导入导出功能缺失是当前最严重的问题,必须优先解决。
推荐: 保持当前架构设计,立即修复导入导出功能,这个项目值得继续开发。
"理论和实践有时会冲突。理论输。每次都是如此。" - Linus Torvalds
这个项目正确地选择了实践。