@darrenjcoxon/codeguard 1.0.0
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/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/agent-report.d.ts +36 -0
- package/dist/agent-report.d.ts.map +1 -0
- package/dist/agent-report.js +329 -0
- package/dist/agent-report.js.map +1 -0
- package/dist/ai-summary.d.ts +55 -0
- package/dist/ai-summary.d.ts.map +1 -0
- package/dist/ai-summary.js +267 -0
- package/dist/ai-summary.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +199 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +63 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +331 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/scanners/complexity.d.ts +29 -0
- package/dist/scanners/complexity.d.ts.map +1 -0
- package/dist/scanners/complexity.js +378 -0
- package/dist/scanners/complexity.js.map +1 -0
- package/dist/scanners/eslint.d.ts +21 -0
- package/dist/scanners/eslint.d.ts.map +1 -0
- package/dist/scanners/eslint.js +196 -0
- package/dist/scanners/eslint.js.map +1 -0
- package/dist/scanners/gitleaks.d.ts +21 -0
- package/dist/scanners/gitleaks.d.ts.map +1 -0
- package/dist/scanners/gitleaks.js +158 -0
- package/dist/scanners/gitleaks.js.map +1 -0
- package/dist/scanners/index.d.ts +56 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +71 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/npm-audit.d.ts +19 -0
- package/dist/scanners/npm-audit.d.ts.map +1 -0
- package/dist/scanners/npm-audit.js +176 -0
- package/dist/scanners/npm-audit.js.map +1 -0
- package/dist/scanners/semgrep.d.ts +22 -0
- package/dist/scanners/semgrep.d.ts.map +1 -0
- package/dist/scanners/semgrep.js +175 -0
- package/dist/scanners/semgrep.js.map +1 -0
- package/dist/types.d.ts +522 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +194 -0
- package/dist/types.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gitleaks Scanner
|
|
3
|
+
*
|
|
4
|
+
* Secret detection scanner using Gitleaks CLI
|
|
5
|
+
* Covers: secret category
|
|
6
|
+
*/
|
|
7
|
+
import { execSync, exec } from 'child_process';
|
|
8
|
+
import { promisify } from 'util';
|
|
9
|
+
const execAsync = promisify(exec);
|
|
10
|
+
export class GitleaksScanner {
|
|
11
|
+
name = 'gitleaks';
|
|
12
|
+
categories = ['secret'];
|
|
13
|
+
async isAvailable() {
|
|
14
|
+
try {
|
|
15
|
+
execSync('gitleaks version', { stdio: 'pipe' });
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async scan(target, config) {
|
|
23
|
+
const startTime = Date.now();
|
|
24
|
+
if (!await this.isAvailable()) {
|
|
25
|
+
return {
|
|
26
|
+
scanner: this.name,
|
|
27
|
+
success: false,
|
|
28
|
+
error: 'Gitleaks not installed. Install with: brew install gitleaks (or download from GitHub)',
|
|
29
|
+
findings: [],
|
|
30
|
+
metrics: { duration: Date.now() - startTime }
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const findings = await this.runGitleaks(target);
|
|
35
|
+
return {
|
|
36
|
+
scanner: this.name,
|
|
37
|
+
success: true,
|
|
38
|
+
findings,
|
|
39
|
+
metrics: {
|
|
40
|
+
duration: Date.now() - startTime,
|
|
41
|
+
filesScanned: findings.length > 0 ? new Set(findings.map(f => f.file)).size : 0
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return {
|
|
47
|
+
scanner: this.name,
|
|
48
|
+
success: false,
|
|
49
|
+
error: error instanceof Error ? error.message : String(error),
|
|
50
|
+
findings: [],
|
|
51
|
+
metrics: { duration: Date.now() - startTime }
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async runGitleaks(target) {
|
|
56
|
+
// Use 'dir' mode for scanning directories, 'git' mode for git repos
|
|
57
|
+
const scanMode = target.git ? 'git' : 'dir';
|
|
58
|
+
const cmd = `gitleaks ${scanMode} --source "${target.path}" --report-format json --report-path /dev/stdout --no-banner 2>/dev/null || true`;
|
|
59
|
+
try {
|
|
60
|
+
const { stdout } = await execAsync(cmd, {
|
|
61
|
+
timeout: 120000, // 2 minutes
|
|
62
|
+
maxBuffer: 10 * 1024 * 1024
|
|
63
|
+
});
|
|
64
|
+
if (!stdout.trim() || stdout.trim() === '[]') {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const findings = JSON.parse(stdout);
|
|
68
|
+
return this.transformFindings(findings);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
// Try to parse output even on error
|
|
72
|
+
if (error.stdout) {
|
|
73
|
+
try {
|
|
74
|
+
const findings = JSON.parse(error.stdout);
|
|
75
|
+
return this.transformFindings(findings);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Empty or invalid output - no findings
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
transformFindings(gitleaksFindings) {
|
|
86
|
+
return gitleaksFindings.map(gf => {
|
|
87
|
+
const severity = this.determineSeverity(gf);
|
|
88
|
+
// Redact the actual secret value
|
|
89
|
+
const redactedSecret = this.redactSecret(gf.Secret);
|
|
90
|
+
const finding = {
|
|
91
|
+
id: `gitleaks-${gf.Fingerprint}`,
|
|
92
|
+
source: this.name,
|
|
93
|
+
severity,
|
|
94
|
+
category: 'secret',
|
|
95
|
+
file: gf.File,
|
|
96
|
+
line: gf.StartLine,
|
|
97
|
+
endLine: gf.EndLine,
|
|
98
|
+
column: gf.StartColumn,
|
|
99
|
+
endColumn: gf.EndColumn,
|
|
100
|
+
title: `Exposed Secret: ${gf.RuleID}`,
|
|
101
|
+
description: `${gf.Description}\n\nRedacted value: ${redactedSecret}`,
|
|
102
|
+
snippet: gf.Match ? this.redactSnippet(gf.Match, gf.Secret) : undefined,
|
|
103
|
+
suggestion: this.getSuggestion(gf.RuleID),
|
|
104
|
+
fixAvailable: true,
|
|
105
|
+
autoFixable: false, // Secrets require manual rotation
|
|
106
|
+
ruleId: gf.RuleID,
|
|
107
|
+
confidence: gf.Entropy > 4 ? 'high' : 'medium',
|
|
108
|
+
fingerprint: gf.Fingerprint
|
|
109
|
+
};
|
|
110
|
+
return finding;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
determineSeverity(gf) {
|
|
114
|
+
const ruleId = gf.RuleID.toLowerCase();
|
|
115
|
+
// Critical: Production/API keys, AWS credentials
|
|
116
|
+
if (ruleId.includes('aws') ||
|
|
117
|
+
ruleId.includes('private-key') ||
|
|
118
|
+
ruleId.includes('api-key') ||
|
|
119
|
+
ruleId.includes('stripe') ||
|
|
120
|
+
ruleId.includes('github-token')) {
|
|
121
|
+
return 'critical';
|
|
122
|
+
}
|
|
123
|
+
// High: Database credentials, generic secrets
|
|
124
|
+
if (ruleId.includes('password') ||
|
|
125
|
+
ruleId.includes('database') ||
|
|
126
|
+
ruleId.includes('jwt') ||
|
|
127
|
+
ruleId.includes('oauth')) {
|
|
128
|
+
return 'high';
|
|
129
|
+
}
|
|
130
|
+
// Medium: Other secrets
|
|
131
|
+
return 'high'; // Default to high for any exposed secret
|
|
132
|
+
}
|
|
133
|
+
redactSecret(secret) {
|
|
134
|
+
if (secret.length <= 8) {
|
|
135
|
+
return '*'.repeat(secret.length);
|
|
136
|
+
}
|
|
137
|
+
const visible = Math.min(4, Math.floor(secret.length / 4));
|
|
138
|
+
return secret.slice(0, visible) + '*'.repeat(secret.length - visible * 2) + secret.slice(-visible);
|
|
139
|
+
}
|
|
140
|
+
redactSnippet(snippet, secret) {
|
|
141
|
+
if (!secret)
|
|
142
|
+
return snippet;
|
|
143
|
+
return snippet.replace(secret, this.redactSecret(secret));
|
|
144
|
+
}
|
|
145
|
+
getSuggestion(ruleId) {
|
|
146
|
+
const suggestions = {
|
|
147
|
+
'aws-access-key-id': 'Rotate the AWS access key immediately and use environment variables or AWS Secrets Manager',
|
|
148
|
+
'aws-secret-access-key': 'Rotate the AWS secret key immediately and use environment variables or AWS Secrets Manager',
|
|
149
|
+
'github-token': 'Revoke this GitHub token and generate a new one with minimum required permissions',
|
|
150
|
+
'generic-api-key': 'Rotate this API key and store securely using environment variables or a secrets manager',
|
|
151
|
+
'private-key': 'This private key is exposed. Generate a new key pair and revoke the compromised one',
|
|
152
|
+
'jwt-base64': 'Rotate the JWT signing secret and invalidate any tokens signed with the old secret'
|
|
153
|
+
};
|
|
154
|
+
return suggestions[ruleId] || 'Rotate this credential immediately and store it securely using environment variables or a secrets manager';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export default GitleaksScanner;
|
|
158
|
+
//# sourceMappingURL=gitleaks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitleaks.js","sourceRoot":"","sources":["../../src/scanners/gitleaks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scanner Index
|
|
3
|
+
*
|
|
4
|
+
* Exports all available scanners
|
|
5
|
+
*/
|
|
6
|
+
export { SemgrepScanner } from './semgrep.js';
|
|
7
|
+
export { GitleaksScanner } from './gitleaks.js';
|
|
8
|
+
export { NpmAuditScanner } from './npm-audit.js';
|
|
9
|
+
export { ESLintScanner } from './eslint.js';
|
|
10
|
+
export { ComplexityScanner } from './complexity.js';
|
|
11
|
+
import type { Scanner } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Get all available scanners
|
|
14
|
+
* Ordered by priority (security first)
|
|
15
|
+
*/
|
|
16
|
+
export declare function getAllScanners(): Scanner[];
|
|
17
|
+
/**
|
|
18
|
+
* Get scanners by category
|
|
19
|
+
*/
|
|
20
|
+
export declare function getScannersByCategory(categories: string[]): Scanner[];
|
|
21
|
+
/**
|
|
22
|
+
* Scanner coverage matrix for documentation
|
|
23
|
+
*/
|
|
24
|
+
export declare const SCANNER_COVERAGE: {
|
|
25
|
+
semgrep: {
|
|
26
|
+
categories: string[];
|
|
27
|
+
description: string;
|
|
28
|
+
languages: string[];
|
|
29
|
+
requirements: string;
|
|
30
|
+
};
|
|
31
|
+
gitleaks: {
|
|
32
|
+
categories: string[];
|
|
33
|
+
description: string;
|
|
34
|
+
languages: string[];
|
|
35
|
+
requirements: string;
|
|
36
|
+
};
|
|
37
|
+
'npm-audit': {
|
|
38
|
+
categories: string[];
|
|
39
|
+
description: string;
|
|
40
|
+
languages: string[];
|
|
41
|
+
requirements: string;
|
|
42
|
+
};
|
|
43
|
+
eslint: {
|
|
44
|
+
categories: string[];
|
|
45
|
+
description: string;
|
|
46
|
+
languages: string[];
|
|
47
|
+
requirements: string;
|
|
48
|
+
};
|
|
49
|
+
complexity: {
|
|
50
|
+
categories: string[];
|
|
51
|
+
description: string;
|
|
52
|
+
languages: string[];
|
|
53
|
+
requirements: string;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanners/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAOpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,EAAE,CAQ1C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAKrE;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+B5B,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scanner Index
|
|
3
|
+
*
|
|
4
|
+
* Exports all available scanners
|
|
5
|
+
*/
|
|
6
|
+
export { SemgrepScanner } from './semgrep.js';
|
|
7
|
+
export { GitleaksScanner } from './gitleaks.js';
|
|
8
|
+
export { NpmAuditScanner } from './npm-audit.js';
|
|
9
|
+
export { ESLintScanner } from './eslint.js';
|
|
10
|
+
export { ComplexityScanner } from './complexity.js';
|
|
11
|
+
import { SemgrepScanner } from './semgrep.js';
|
|
12
|
+
import { GitleaksScanner } from './gitleaks.js';
|
|
13
|
+
import { NpmAuditScanner } from './npm-audit.js';
|
|
14
|
+
import { ESLintScanner } from './eslint.js';
|
|
15
|
+
import { ComplexityScanner } from './complexity.js';
|
|
16
|
+
/**
|
|
17
|
+
* Get all available scanners
|
|
18
|
+
* Ordered by priority (security first)
|
|
19
|
+
*/
|
|
20
|
+
export function getAllScanners() {
|
|
21
|
+
return [
|
|
22
|
+
new SemgrepScanner(), // Security + Quality (SAST)
|
|
23
|
+
new GitleaksScanner(), // Secrets
|
|
24
|
+
new NpmAuditScanner(), // Dependencies (SCA)
|
|
25
|
+
new ESLintScanner(), // Quality + Style
|
|
26
|
+
new ComplexityScanner() // Complexity + Code Smells
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get scanners by category
|
|
31
|
+
*/
|
|
32
|
+
export function getScannersByCategory(categories) {
|
|
33
|
+
const allScanners = getAllScanners();
|
|
34
|
+
return allScanners.filter(scanner => scanner.categories.some(cat => categories.includes(cat)));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Scanner coverage matrix for documentation
|
|
38
|
+
*/
|
|
39
|
+
export const SCANNER_COVERAGE = {
|
|
40
|
+
semgrep: {
|
|
41
|
+
categories: ['security', 'quality', 'style'],
|
|
42
|
+
description: 'Static Application Security Testing (SAST)',
|
|
43
|
+
languages: ['JavaScript', 'TypeScript', 'Python', 'Go', 'Ruby', 'Java', 'C', 'PHP', 'and more'],
|
|
44
|
+
requirements: 'semgrep CLI'
|
|
45
|
+
},
|
|
46
|
+
gitleaks: {
|
|
47
|
+
categories: ['secret'],
|
|
48
|
+
description: 'Secret and credential detection',
|
|
49
|
+
languages: ['All (content-based scanning)'],
|
|
50
|
+
requirements: 'gitleaks CLI'
|
|
51
|
+
},
|
|
52
|
+
'npm-audit': {
|
|
53
|
+
categories: ['dependency'],
|
|
54
|
+
description: 'Dependency vulnerability scanning',
|
|
55
|
+
languages: ['JavaScript', 'TypeScript (Node.js)'],
|
|
56
|
+
requirements: 'npm'
|
|
57
|
+
},
|
|
58
|
+
eslint: {
|
|
59
|
+
categories: ['quality', 'style', 'security'],
|
|
60
|
+
description: 'JavaScript/TypeScript linting',
|
|
61
|
+
languages: ['JavaScript', 'TypeScript'],
|
|
62
|
+
requirements: 'eslint (project dependency)'
|
|
63
|
+
},
|
|
64
|
+
complexity: {
|
|
65
|
+
categories: ['complexity', 'quality'],
|
|
66
|
+
description: 'Code complexity and smell detection',
|
|
67
|
+
languages: ['JavaScript', 'TypeScript', 'Python', 'Ruby', 'PHP', 'Java', 'C#', 'Go'],
|
|
68
|
+
requirements: 'None (built-in)'
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanners/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO;QACL,IAAI,cAAc,EAAE,EAAO,4BAA4B;QACvD,IAAI,eAAe,EAAE,EAAM,UAAU;QACrC,IAAI,eAAe,EAAE,EAAM,qBAAqB;QAChD,IAAI,aAAa,EAAE,EAAQ,kBAAkB;QAC7C,IAAI,iBAAiB,EAAE,CAAI,2BAA2B;KACvD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAoB;IACxD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAClC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CACzD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,OAAO,EAAE;QACP,UAAU,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC;QAC5C,WAAW,EAAE,4CAA4C;QACzD,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC;QAC/F,YAAY,EAAE,aAAa;KAC5B;IACD,QAAQ,EAAE;QACR,UAAU,EAAE,CAAC,QAAQ,CAAC;QACtB,WAAW,EAAE,iCAAiC;QAC9C,SAAS,EAAE,CAAC,8BAA8B,CAAC;QAC3C,YAAY,EAAE,cAAc;KAC7B;IACD,WAAW,EAAE;QACX,UAAU,EAAE,CAAC,YAAY,CAAC;QAC1B,WAAW,EAAE,mCAAmC;QAChD,SAAS,EAAE,CAAC,YAAY,EAAE,sBAAsB,CAAC;QACjD,YAAY,EAAE,KAAK;KACpB;IACD,MAAM,EAAE;QACN,UAAU,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC;QAC5C,WAAW,EAAE,+BAA+B;QAC5C,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;QACvC,YAAY,EAAE,6BAA6B;KAC5C;IACD,UAAU,EAAE;QACV,UAAU,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC;QACrC,WAAW,EAAE,qCAAqC;QAClD,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC;QACpF,YAAY,EAAE,iBAAiB;KAChC;CACF,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NPM Audit Scanner
|
|
3
|
+
*
|
|
4
|
+
* Dependency vulnerability scanning for JavaScript/Node.js projects
|
|
5
|
+
* Covers: dependency category
|
|
6
|
+
*/
|
|
7
|
+
import { Scanner, ScanTarget, ScannerConfig, ScannerResult, FindingCategory } from '../types.js';
|
|
8
|
+
export declare class NpmAuditScanner implements Scanner {
|
|
9
|
+
name: string;
|
|
10
|
+
categories: FindingCategory[];
|
|
11
|
+
isAvailable(): Promise<boolean>;
|
|
12
|
+
scan(target: ScanTarget, config?: ScannerConfig): Promise<ScannerResult>;
|
|
13
|
+
private runNpmAudit;
|
|
14
|
+
private transformFindings;
|
|
15
|
+
private mapSeverity;
|
|
16
|
+
private getFixInfo;
|
|
17
|
+
}
|
|
18
|
+
export default NpmAuditScanner;
|
|
19
|
+
//# sourceMappingURL=npm-audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-audit.d.ts","sourceRoot":"","sources":["../../src/scanners/npm-audit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EACL,OAAO,EACP,UAAU,EACV,aAAa,EACb,aAAa,EAEb,eAAe,EAGhB,MAAM,aAAa,CAAC;AAuDrB,qBAAa,eAAgB,YAAW,OAAO;IAC7C,IAAI,SAAe;IACnB,UAAU,EAAE,eAAe,EAAE,CAAkB;IAEzC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;YA+ChE,WAAW;IA8BzB,OAAO,CAAC,iBAAiB;IA2CzB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,UAAU;CAuCnB;AAED,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NPM Audit Scanner
|
|
3
|
+
*
|
|
4
|
+
* Dependency vulnerability scanning for JavaScript/Node.js projects
|
|
5
|
+
* Covers: dependency category
|
|
6
|
+
*/
|
|
7
|
+
import { exec } from 'child_process';
|
|
8
|
+
import { promisify } from 'util';
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
import { generateFingerprint } from '../types.js';
|
|
12
|
+
const execAsync = promisify(exec);
|
|
13
|
+
export class NpmAuditScanner {
|
|
14
|
+
name = 'npm-audit';
|
|
15
|
+
categories = ['dependency'];
|
|
16
|
+
async isAvailable() {
|
|
17
|
+
try {
|
|
18
|
+
const { stdout } = await execAsync('npm --version', { timeout: 5000 });
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async scan(target, config) {
|
|
26
|
+
const startTime = Date.now();
|
|
27
|
+
// Check if this is a Node.js project
|
|
28
|
+
const packageJsonPath = join(target.path, 'package.json');
|
|
29
|
+
if (!existsSync(packageJsonPath)) {
|
|
30
|
+
return {
|
|
31
|
+
scanner: this.name,
|
|
32
|
+
success: true,
|
|
33
|
+
findings: [],
|
|
34
|
+
metrics: { duration: Date.now() - startTime },
|
|
35
|
+
metadata: { skipped: true, reason: 'No package.json found' }
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (!await this.isAvailable()) {
|
|
39
|
+
return {
|
|
40
|
+
scanner: this.name,
|
|
41
|
+
success: false,
|
|
42
|
+
error: 'npm not available',
|
|
43
|
+
findings: [],
|
|
44
|
+
metrics: { duration: Date.now() - startTime }
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const findings = await this.runNpmAudit(target);
|
|
49
|
+
return {
|
|
50
|
+
scanner: this.name,
|
|
51
|
+
success: true,
|
|
52
|
+
findings,
|
|
53
|
+
metrics: {
|
|
54
|
+
duration: Date.now() - startTime
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return {
|
|
60
|
+
scanner: this.name,
|
|
61
|
+
success: false,
|
|
62
|
+
error: error instanceof Error ? error.message : String(error),
|
|
63
|
+
findings: [],
|
|
64
|
+
metrics: { duration: Date.now() - startTime }
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async runNpmAudit(target) {
|
|
69
|
+
const cmd = `cd "${target.path}" && npm audit --json 2>/dev/null || true`;
|
|
70
|
+
try {
|
|
71
|
+
const { stdout } = await execAsync(cmd, {
|
|
72
|
+
timeout: 120000,
|
|
73
|
+
maxBuffer: 10 * 1024 * 1024
|
|
74
|
+
});
|
|
75
|
+
if (!stdout.trim()) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
const output = JSON.parse(stdout);
|
|
79
|
+
return this.transformFindings(output, target.path);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
// npm audit returns exit code 1 when vulnerabilities exist
|
|
83
|
+
if (error.stdout) {
|
|
84
|
+
try {
|
|
85
|
+
const output = JSON.parse(error.stdout);
|
|
86
|
+
return this.transformFindings(output, target.path);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
transformFindings(output, basePath) {
|
|
96
|
+
const findings = [];
|
|
97
|
+
for (const [pkgName, vuln] of Object.entries(output.vulnerabilities || {})) {
|
|
98
|
+
// Get the most specific vulnerability info
|
|
99
|
+
const viaDetails = vuln.via.filter(v => typeof v === 'object')[0];
|
|
100
|
+
if (!viaDetails)
|
|
101
|
+
continue;
|
|
102
|
+
const severity = this.mapSeverity(vuln.severity);
|
|
103
|
+
const fixInfo = this.getFixInfo(vuln.fixAvailable);
|
|
104
|
+
const finding = {
|
|
105
|
+
id: `npm-${pkgName}-${viaDetails.source || Date.now()}`,
|
|
106
|
+
source: this.name,
|
|
107
|
+
severity,
|
|
108
|
+
category: 'dependency',
|
|
109
|
+
file: 'package.json',
|
|
110
|
+
title: `Vulnerable dependency: ${pkgName}`,
|
|
111
|
+
description: `${viaDetails.title || 'Security vulnerability'}\n\n` +
|
|
112
|
+
`Package: ${pkgName}\n` +
|
|
113
|
+
`Vulnerable versions: ${vuln.range}\n` +
|
|
114
|
+
`Dependency path: ${vuln.isDirect ? 'Direct dependency' : 'Transitive dependency'}\n` +
|
|
115
|
+
(viaDetails.url ? `\nMore info: ${viaDetails.url}` : ''),
|
|
116
|
+
cwe: viaDetails.cwe?.[0] ? `CWE-${viaDetails.cwe[0]}` : undefined,
|
|
117
|
+
cvss: viaDetails.cvss?.score,
|
|
118
|
+
suggestion: fixInfo.suggestion,
|
|
119
|
+
fixAvailable: fixInfo.available,
|
|
120
|
+
autoFixable: fixInfo.autoFixable,
|
|
121
|
+
ruleId: `npm-advisory-${viaDetails.source}`,
|
|
122
|
+
ruleUrl: viaDetails.url,
|
|
123
|
+
confidence: 'high',
|
|
124
|
+
effort: fixInfo.effort,
|
|
125
|
+
fingerprint: ''
|
|
126
|
+
};
|
|
127
|
+
finding.fingerprint = generateFingerprint(finding);
|
|
128
|
+
findings.push(finding);
|
|
129
|
+
}
|
|
130
|
+
return findings;
|
|
131
|
+
}
|
|
132
|
+
mapSeverity(npmSeverity) {
|
|
133
|
+
const mapping = {
|
|
134
|
+
'critical': 'critical',
|
|
135
|
+
'high': 'high',
|
|
136
|
+
'moderate': 'medium',
|
|
137
|
+
'low': 'low',
|
|
138
|
+
'info': 'info'
|
|
139
|
+
};
|
|
140
|
+
return mapping[npmSeverity.toLowerCase()] || 'medium';
|
|
141
|
+
}
|
|
142
|
+
getFixInfo(fixAvailable) {
|
|
143
|
+
if (fixAvailable === true) {
|
|
144
|
+
return {
|
|
145
|
+
available: true,
|
|
146
|
+
autoFixable: true,
|
|
147
|
+
suggestion: 'Run `npm audit fix` to automatically fix this vulnerability',
|
|
148
|
+
effort: 'trivial'
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (typeof fixAvailable === 'object' && fixAvailable !== null) {
|
|
152
|
+
if (fixAvailable.isSemVerMajor) {
|
|
153
|
+
return {
|
|
154
|
+
available: true,
|
|
155
|
+
autoFixable: false,
|
|
156
|
+
suggestion: `Update to ${fixAvailable.name}@${fixAvailable.version} (breaking change - review required). Run \`npm audit fix --force\` with caution`,
|
|
157
|
+
effort: 'medium'
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
available: true,
|
|
162
|
+
autoFixable: true,
|
|
163
|
+
suggestion: `Update to ${fixAvailable.name}@${fixAvailable.version}. Run \`npm audit fix\``,
|
|
164
|
+
effort: 'easy'
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
available: false,
|
|
169
|
+
autoFixable: false,
|
|
170
|
+
suggestion: 'No fix currently available. Consider using an alternative package or implementing mitigations',
|
|
171
|
+
effort: 'hard'
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export default NpmAuditScanner;
|
|
176
|
+
//# sourceMappingURL=npm-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-audit.js","sourceRoot":"","sources":["../../src/scanners/npm-audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semgrep Scanner
|
|
3
|
+
*
|
|
4
|
+
* Provides SAST scanning using Semgrep CLI with fallback to MCP
|
|
5
|
+
* Covers: security, quality, style categories
|
|
6
|
+
*/
|
|
7
|
+
import { Scanner, ScanTarget, ScannerConfig, ScannerResult, FindingCategory } from '../types.js';
|
|
8
|
+
export declare class SemgrepScanner implements Scanner {
|
|
9
|
+
name: string;
|
|
10
|
+
categories: FindingCategory[];
|
|
11
|
+
private rulesets;
|
|
12
|
+
constructor(rulesets?: string[]);
|
|
13
|
+
isAvailable(): Promise<boolean>;
|
|
14
|
+
scan(target: ScanTarget, config?: ScannerConfig): Promise<ScannerResult>;
|
|
15
|
+
private runSemgrep;
|
|
16
|
+
private transformFindings;
|
|
17
|
+
private mapSeverity;
|
|
18
|
+
private mapCategory;
|
|
19
|
+
private mapConfidence;
|
|
20
|
+
}
|
|
21
|
+
export default SemgrepScanner;
|
|
22
|
+
//# sourceMappingURL=semgrep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semgrep.d.ts","sourceRoot":"","sources":["../../src/scanners/semgrep.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EACL,OAAO,EACP,UAAU,EACV,aAAa,EACb,aAAa,EAEb,eAAe,EAGhB,MAAM,aAAa,CAAC;AAiCrB,qBAAa,cAAe,YAAW,OAAO;IAC5C,IAAI,SAAa;IACjB,UAAU,EAAE,eAAe,EAAE,CAAoC;IAEjE,OAAO,CAAC,QAAQ,CAAW;gBAEf,QAAQ,GAAE,MAAM,EAAa;IAYnC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;YAoChE,UAAU;IA0CxB,OAAO,CAAC,iBAAiB;IAkCzB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,aAAa;CAQtB;AAED,eAAe,cAAc,CAAC"}
|