import { describe, it, expect } from 'vitest'; import { SUSPICIOUS_MESSAGE_PATTERNS, scanCommitMessagePatterns, scanCommitMessage, defaultLlmJudgeStub, } from './commit-message-scanner.mjs'; describe('SUSPICIOUS_MESSAGE_PATTERNS', () => { it('is a non-empty array of RegExp', () => { expect(Array.isArray(SUSPICIOUS_MESSAGE_PATTERNS)).toBe(true); expect(SUSPICIOUS_MESSAGE_PATTERNS.length).toBeGreaterThanOrEqual(5); expect(SUSPICIOUS_MESSAGE_PATTERNS.every((r) => r instanceof RegExp)).toBe(true); }); }); describe('scanCommitMessagePatterns (sync regex pass)', () => { it('allows a normal conventional-commit message', () => { const r = scanCommitMessagePatterns('feat(router-gate): add static scanner (Stream C)'); expect(r.block).toBe(false); }); it('allows a short-SHA range reference', () => { expect(scanCommitMessagePatterns('ci: rebase ef19b9f2..46c43169').block).toBe(false); }); it('blocks an external non-whitelist URL', () => { const r = scanCommitMessagePatterns('docs: see http://evil.example.com/payload'); expect(r.block).toBe(true); expect(r.reason).toBe('commit_message_suspicious_content'); }); it('allows a whitelisted anthropic / liderra URL', () => { expect(scanCommitMessagePatterns('docs: per https://docs.anthropic.com/x').block).toBe(false); expect(scanCommitMessagePatterns('docs: see https://liderra.ru/x').block).toBe(false); }); it('blocks a long hex blob (potential exfil)', () => { expect(scanCommitMessagePatterns('chore: ' + 'a'.repeat(48)).block).toBe(true); }); it('blocks a base64-like blob', () => { // 80 continuous base64-charset chars (incl. non-hex letters + digits, no '=') // → exercises the base64 pattern specifically, not the hex pattern. expect(scanCommitMessagePatterns('chore: ' + 'Zm9vYmFyYmF6cXV4'.repeat(5)).block).toBe(true); }); it('blocks script tag / php tag / template injection', () => { expect(scanCommitMessagePatterns('fix: ').block).toBe(true); expect(scanCommitMessagePatterns('fix: ').block).toBe(true); expect(scanCommitMessagePatterns('fix: ${process.env.SECRET}').block).toBe(true); }); it('blocks hex / unicode escape sequences', () => { expect(scanCommitMessagePatterns('fix: \\x41\\x42').block).toBe(true); expect(scanCommitMessagePatterns('fix: \\u0041').block).toBe(true); }); }); describe('defaultLlmJudgeStub', () => { it('returns a NO verdict marked as a stub', async () => { const v = await defaultLlmJudgeStub({ prompt: 'x' }); expect(v.verdict).toBe('NO'); expect(v.stub).toBe(true); }); }); describe('scanCommitMessage (async, with injected judge)', () => { it('blocks on regex before ever calling the judge', async () => { let judgeCalled = false; const llmJudge = async () => { judgeCalled = true; return { verdict: 'NO' }; }; const r = await scanCommitMessage('docs: http://evil.example.com', { llmJudge }); expect(r.block).toBe(true); expect(r.reason).toBe('commit_message_suspicious_content'); expect(judgeCalled).toBe(false); }); it('blocks when the judge returns YES on a regex-clean message', async () => { const llmJudge = async () => ({ verdict: 'YES' }); const r = await scanCommitMessage('feat: innocuous looking message', { llmJudge }); expect(r.block).toBe(true); expect(r.reason).toBe('commit_message_llm_judge_positive'); }); it('allows when regex clean and judge returns NO', async () => { const llmJudge = async () => ({ verdict: 'NO' }); const r = await scanCommitMessage('feat: add Stream C scanners', { llmJudge }); expect(r.block).toBe(false); }); it('uses the default stub (allow on clean) when no judge injected', async () => { const r = await scanCommitMessage('feat: add Stream C scanners'); expect(r.block).toBe(false); }); it('accepts a plain-string judge return ("YES"/"NO")', async () => { const r = await scanCommitMessage('feat: clean', { llmJudge: async () => 'YES' }); expect(r.block).toBe(true); }); }); describe('scanCommitMessagePatterns — project_url_whitelist (D3/D4)', () => { it('default (no opts) keeps liderra whitelisted', () => { expect(scanCommitMessagePatterns('docs: https://liderra.ru/x').block).toBe(false); }); it('empty whitelist → liderra blocked (fail-CLOSED), anthropic ok', () => { expect(scanCommitMessagePatterns('docs: https://liderra.ru/x', { urlWhitelist: [] }).block).toBe(true); expect(scanCommitMessagePatterns('docs: https://docs.anthropic.com/x', { urlWhitelist: [] }).block).toBe(false); }); it('config whitelist admits own domain', () => { expect(scanCommitMessagePatterns('docs: https://liderra.ru/x', { urlWhitelist: ['liderra.ru'] }).block).toBe(false); }); });