diff --git a/server/src/db/repository.ts b/server/src/db/repository.ts index b2f7e0e..21a203a 100644 --- a/server/src/db/repository.ts +++ b/server/src/db/repository.ts @@ -2700,8 +2700,24 @@ export class MysqlRepository { FROM platform_configs WHERE status = 1 `); + // 移动端公开配置:严禁下发任何密钥/风控内部数据(该接口无需登录) + const PUBLIC_EXCLUDED_KEYS = new Set(['security_words', 'map_location_config']); + const SENSITIVE_FIELD = /(secret|private|apiv3|api_v3|password|passwd|token|pem|cert|mchid)/i; + const stripSensitive = (val: any): any => { + if (Array.isArray(val)) return val.map(stripSensitive); + if (val && typeof val === 'object') { + const out: { [k: string]: any } = {}; + for (const [k, v] of Object.entries(val)) { + if (SENSITIVE_FIELD.test(k)) continue; + out[k] = stripSensitive(v); + } + return out; + } + return val; + }; const result: { [key: string]: any } = {}; for (const r of rows) { + if (PUBLIC_EXCLUDED_KEYS.has(r.configKey)) continue; let val = r.valueJson; if (typeof val === 'string') { try { @@ -2715,7 +2731,7 @@ export class MysqlRepository { mchIdConfigured: Boolean(val.mchId && val.apiV3Key && val.privateKey) }; } else { - result[r.configKey] = val; + result[r.configKey] = stripSensitive(val); } } return result; diff --git a/server/tests/public-config-privacy.spec.ts b/server/tests/public-config-privacy.spec.ts new file mode 100644 index 0000000..f599d0e --- /dev/null +++ b/server/tests/public-config-privacy.spec.ts @@ -0,0 +1,23 @@ +// 已读取AGENTS.md +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * 第七十三批回归闸门:移动端公开配置不得泄露密钥/风控数据。 + * 背景:/api/system/configs 无需登录,曾原样下发 map_location_config(含 SecretKey) 与 security_words(风控词库)。 + */ +describe('第七十三批公开配置隐私闸门', () => { + const root = path.resolve(__dirname, '../../'); + const repo = fs.readFileSync(path.join(root, 'server/src/db/repository.ts'), 'utf-8'); + + it('公开配置排除风控词库与地图密钥配置', () => { + expect(repo).toContain("const PUBLIC_EXCLUDED_KEYS = new Set(['security_words', 'map_location_config'])"); + expect(repo).toContain('if (PUBLIC_EXCLUDED_KEYS.has(r.configKey)) continue;'); + }); + + it('公开配置递归剔除敏感字段', () => { + expect(repo).toContain('const stripSensitive = (val: any)'); + expect(repo).toContain('if (SENSITIVE_FIELD.test(k)) continue;'); + expect(repo).toContain('result[r.configKey] = stripSensitive(val);'); + }); +});