fix(security): 认证/越权/注入/上传/凭据全链路加固
由 OCR(open-codereview.ai,deepseek-v4-flash)审查驱动修复: - JWT 生产必填、密码 8-72 字节、防枚举;全局 ValidationPipe - classes/dashboard/schedules/students/attendance/archive/exams 越权与 IDOR 修复 - LIKE 通配符转义(14 处);上传 10MB 上限 + MIME 白名单 + 附件 XSS - 集成配置 appSecret AES 加密 + 回填脚本;审计 best-effort;IP 来源防伪造 Reviewed-by: OCR (open-codereview.ai)
This commit is contained in:
67
apps/server/scripts/encrypt-integration-secrets.ts
Normal file
67
apps/server/scripts/encrypt-integration-secrets.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
import datasource from '../datasource';
|
||||
import { encryptSecret, isEncryptedSecret } from '../src/integration/config/secret-crypto';
|
||||
import { IntegrationConfigDetail } from '../src/integration/entities/integration-config.entity';
|
||||
|
||||
/** integration_config_detail.content JSON 中与本次回填相关的结构。 */
|
||||
interface StoredConfigContent {
|
||||
type?: unknown;
|
||||
verify?: unknown;
|
||||
config?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
// 主动检查加密密钥:缺失时 getEncryptionKey() 会静默使用开发回退密钥,
|
||||
// 绝不能用回退密钥加密生产数据,因此未配置时直接报错退出。
|
||||
if (!process.env.AI_CONFIG_ENCRYPTION_KEY) {
|
||||
throw new Error(
|
||||
'AI_CONFIG_ENCRYPTION_KEY 未设置:为避免使用开发回退密钥加密数据,请先配置 AI_CONFIG_ENCRYPTION_KEY 再运行回填脚本',
|
||||
);
|
||||
}
|
||||
|
||||
await datasource.initialize();
|
||||
console.log('已连接数据库,开始回填第三方集成配置 appSecret 加密...');
|
||||
|
||||
try {
|
||||
const repo = datasource.getRepository(IntegrationConfigDetail);
|
||||
const rows = await repo.find();
|
||||
let processed = 0;
|
||||
|
||||
for (const row of rows) {
|
||||
if (!row.content) continue;
|
||||
|
||||
let parsed: StoredConfigContent;
|
||||
try {
|
||||
parsed = JSON.parse(row.content) as StoredConfigContent;
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
|
||||
const config = parsed.config;
|
||||
if (!config || typeof config !== 'object' || Array.isArray(config)) continue;
|
||||
|
||||
const appSecret = config.appSecret;
|
||||
if (typeof appSecret !== 'string' || !appSecret || isEncryptedSecret(appSecret)) continue;
|
||||
|
||||
config.appSecret = encryptSecret(appSecret);
|
||||
row.content = JSON.stringify(parsed);
|
||||
await repo.save(row);
|
||||
processed += 1;
|
||||
}
|
||||
|
||||
console.log(`回填完成:共处理 ${processed} 行(加密 appSecret)`);
|
||||
} finally {
|
||||
// 无论成功还是失败都关闭连接池,避免泄漏
|
||||
try {
|
||||
await datasource.destroy();
|
||||
} catch {
|
||||
// 销毁失败不影响主流程结果
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('回填失败:', error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user