Files
metona-ai-desktop/electron/utils/__tests__/mask.test.ts
T
thzxx 4cd6e997b5
CI / 类型检查 + Lint + 单元测试 (push) Failing after 9m45s
CI / 全量测试 (Electron ABI) (push) Failing after 6m28s
CI / 产物编译验证 (push) Successful in 11m18s
feat: v0.8.2 安全纵深补全 · 协议保真 · 断链修复 — 图片SSRF/根MEMORY.md保护根治 · Anthropic thinking回传+pause_turn续传 · 2523 用例全量回归 + E2E 扩充
2026-09-08 14:30:27 +08:00

76 lines
2.6 KiB
TypeScript

/**
* v0.8.2 P1-5: 敏感值脱敏单源工具测试
*
* 锁定契约:
* - 键名归一化匹配(api_key / authKey / Authorization 等形态均命中)
* - 长值保留后 4 位、短值完全掩码
* - 嵌套对象/数组递归;非敏感字段原样保留
* - 循环引用与深度上限防护(防御恶意构造的工具参数)
* - 原对象不被修改
*/
import { describe, it, expect } from 'vitest';
import { deepMaskSensitive, maskSensitiveValue } from '../mask';
describe('maskSensitiveValue', () => {
it('长值保留后 4 位', () => {
expect(maskSensitiveValue('sk-abcdefgh12345678')).toBe('***5678');
});
it('短值(≤4)完全掩码', () => {
expect(maskSensitiveValue('abc')).toBe('***');
expect(maskSensitiveValue('abcd')).toBe('***');
});
});
describe('deepMaskSensitive', () => {
it('顶层与嵌套的敏感键均被掩码', () => {
const input = {
url: 'https://api.example.com',
headers: {
Authorization: 'Bearer sk-abcdefgh12345678',
'content-type': 'application/json',
},
api_key: 'sk-abcdefgh12345678',
nested: { authToken: 'token-1234567890' },
};
const out = deepMaskSensitive(input) as typeof input;
expect(out.url).toBe('https://api.example.com');
expect(out['api_key']).toBe('***5678');
expect((out.headers as Record<string, string>).Authorization).toBe('***5678');
expect((out.headers as Record<string, string>)['content-type']).toBe('application/json');
expect((out.nested as { authToken: string }).authToken).toBe('***7890');
});
it('数组内对象同样脱敏', () => {
const out = deepMaskSensitive([{ secret: 'supersecret-value-42' }, { ok: 1 }]) as Array<
Record<string, unknown>
>;
expect(out[0].secret).toBe('***e-42');
expect(out[1].ok).toBe(1);
});
it('原对象不被修改', () => {
const input = { api_key: 'sk-abcdefgh12345678' };
deepMaskSensitive(input);
expect(input.api_key).toBe('sk-abcdefgh12345678');
});
it('循环引用与深度上限不抛错', () => {
const a: Record<string, unknown> = { name: 'a' };
a.self = a;
const out = deepMaskSensitive(a) as Record<string, unknown>;
expect(out.name).toBe('a');
expect(out.self).toBe('[circular]');
const deep: Record<string, unknown> = { v: 0 };
let cur = deep;
for (let i = 0; i < 20; i++) {
cur.next = { v: i + 1 };
cur = cur.next as Record<string, unknown>;
}
const deepOut = deepMaskSensitive(deep) as Record<string, unknown>;
expect(deepOut.v).toBe(0);
expect(JSON.stringify(deepOut)).toContain('depth-limit');
});
});