Files
gongxue-base/apps/server/scripts/encrypt-integration-secrets.ts
wangziqi 99ea931409 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)
2026-08-09 21:29:22 +08:00

68 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// <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;
});