文件
shanghaipeiwan/server/tests/startup-selfcheck.spec.ts
xcbyy d06bf11740 security: 危险兜底默认关闭(secure by default)——修复 NODE_ENV 未设导致的身份伪造/沙箱支付/隐私泄露
根因:线上 NODE_ENV 未设为 production 时,以下"开发兜底"全部自动生效:
- resolveSecureUserId 信任客户端声明的 userId → 任意用户身份伪造
- ALLOW_SANDBOX_PAY = ... || !IS_PRODUCTION → 无真实收款即可推进订单(资损)
- GET /api/users/:id 按"本人"返回余额/佣金/手机号 → 隐私泄露

修复(兜底改为必须显式开启):
- 新增 ALLOW_INSECURE_DEV_AUTH(默认 false);resolveSecureUserId 改为 `if (IS_PRODUCTION || !ALLOW_INSECURE_DEV_AUTH) 401`
- ALLOW_SANDBOX_PAY 改为仅 `process.env.ALLOW_SANDBOX_PAY === '1'`
- assertCompanionActor 与用户资料"本人视角"兜底加 ALLOW_INSECURE_DEV_AUTH 限制
- /api/health 新增 mode 与 sandboxPayAllowed;启动自检打印两个危险开关并告警
- 文档补充危险开关说明(生产禁止开启)

验证:本地模拟 NODE_ENV 未设 → 通知/订单/下单 均 401、用户资料不泄露隐私、沙箱支付关闭;
开启 ALLOW_INSECURE_DEV_AUTH=1 后联调能力保留;production 模式行为一致。(冒烟 13/13)
新增 secure-default-auth.spec.ts(103 套件/696 用例全绿)
2026-10-20 16:35:04 +08:00

28 行
1.1 KiB
TypeScript

// 已读取AGENTS.md
import * as fs from 'fs';
import * as path from 'path';
/**
* 第五十四批回归闸门:启动配置自检(部署验收)
*/
describe('第五十四批启动自检闸门', () => {
const rootDir = path.resolve(__dirname, '../../');
const indexCode = fs.readFileSync(path.join(rootDir, 'server/src/index.ts'), 'utf-8');
it('提供启动自检并输出就绪状态(不泄露密钥)', () => {
expect(indexCode).toContain('async function logStartupConfigSelfCheck(');
const start = indexCode.indexOf('async function logStartupConfigSelfCheck(');
const block = indexCode.slice(start, start + 2600);
expect(block).toContain('运行模式=');
expect(block).toContain('实盘就绪=');
expect(block).toContain('未设置 ADMIN_TOKEN_SECRET');
// 不得打印密钥值,仅打印是否设置
expect(block).not.toContain('${ADMIN_TOKEN_SECRET}');
expect(block).not.toContain('${USER_TOKEN_SECRET}');
});
it('bootstrap 中调用自检', () => {
expect(indexCode).toContain('await logStartupConfigSelfCheck();');
});
});