import { describe, it, expect } from 'vitest'; import { decide } from './enforce-mcp-classification.mjs'; describe('enforce-mcp-classification decide()', () => { it('allows non-mcp tools (no-op)', () => { expect(decide({ toolName: 'Bash', toolInput: { command: 'ls' } }).block).toBe(false); }); it('blocks an unknown mcp tool (default-deny)', () => { const r = decide({ toolName: 'mcp__unknown__doSomething', toolInput: {} }); expect(r.block).toBe(true); expect(r.reason).toMatch(/not in gate-config classification/); }); }); // 7.3 (Блок 4.3) — скан ИСХОДЯЩЕГО (egress): даже разрешённый классификатором MCP-вызов не // должен выносить наружу секреты (общий secret-scan) или использовать exfil-схемы // (data:base64 / file:// / IP-литерал URL) или раздутый payload. fail-close на egress. import { scanEgress } from './enforce-mcp-classification.mjs'; describe('scanEgress (7.3): скан исходящего MCP-payload на exfil', () => { it('секрет в аргументах (AWS) → block', () => { const r = scanEgress({ key: 'AKIAIOSFODNN7EXAMPLE' }); expect(r.block).toBe(true); expect(r.reason).toMatch(/секрет/i); }); it('data:base64 URI → block (exfil-вектор)', () => { expect(scanEgress({ url: 'data:text/plain;base64,SGVsbG8=' }).block).toBe(true); }); it('file:// схема → block', () => { expect(scanEgress({ src: 'file:///etc/passwd' }).block).toBe(true); }); it('IP-литерал URL → block (обход DNS/allowlist)', () => { expect(scanEgress({ url: 'http://203.0.113.5/collect' }).block).toBe(true); }); it('раздутый payload → block', () => { expect(scanEgress({ blob: 'x'.repeat(50) }, { maxBytes: 20 }).block).toBe(true); }); it('чистые аргументы → не block', () => { expect(scanEgress({ key: 'user:42:profile' }).block).toBe(false); }); }); describe('decide 7.3: egress-скан даже на разрешённом классификатором MCP-вызове', () => { it('read_only mcp + секрет в аргументах → block (egress)', () => { const r = decide({ toolName: 'mcp__redis__get', toolInput: { key: 'ghp_0123456789abcdefghijklmnopqrstuvwxyz' } }); expect(r.block).toBe(true); expect(r.reason).toMatch(/egress/i); }); it('read_only mcp + чистые аргументы → allow', () => { expect(decide({ toolName: 'mcp__redis__get', toolInput: { key: 'session:abc' } }).block).toBe(false); }); });