@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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -0
  3. package/dist/agent-report.d.ts +36 -0
  4. package/dist/agent-report.d.ts.map +1 -0
  5. package/dist/agent-report.js +329 -0
  6. package/dist/agent-report.js.map +1 -0
  7. package/dist/ai-summary.d.ts +55 -0
  8. package/dist/ai-summary.d.ts.map +1 -0
  9. package/dist/ai-summary.js +267 -0
  10. package/dist/ai-summary.js.map +1 -0
  11. package/dist/cli.d.ts +9 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +199 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/index.d.ts +23 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +27 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/orchestrator.d.ts +63 -0
  20. package/dist/orchestrator.d.ts.map +1 -0
  21. package/dist/orchestrator.js +331 -0
  22. package/dist/orchestrator.js.map +1 -0
  23. package/dist/scanners/complexity.d.ts +29 -0
  24. package/dist/scanners/complexity.d.ts.map +1 -0
  25. package/dist/scanners/complexity.js +378 -0
  26. package/dist/scanners/complexity.js.map +1 -0
  27. package/dist/scanners/eslint.d.ts +21 -0
  28. package/dist/scanners/eslint.d.ts.map +1 -0
  29. package/dist/scanners/eslint.js +196 -0
  30. package/dist/scanners/eslint.js.map +1 -0
  31. package/dist/scanners/gitleaks.d.ts +21 -0
  32. package/dist/scanners/gitleaks.d.ts.map +1 -0
  33. package/dist/scanners/gitleaks.js +158 -0
  34. package/dist/scanners/gitleaks.js.map +1 -0
  35. package/dist/scanners/index.d.ts +56 -0
  36. package/dist/scanners/index.d.ts.map +1 -0
  37. package/dist/scanners/index.js +71 -0
  38. package/dist/scanners/index.js.map +1 -0
  39. package/dist/scanners/npm-audit.d.ts +19 -0
  40. package/dist/scanners/npm-audit.d.ts.map +1 -0
  41. package/dist/scanners/npm-audit.js +176 -0
  42. package/dist/scanners/npm-audit.js.map +1 -0
  43. package/dist/scanners/semgrep.d.ts +22 -0
  44. package/dist/scanners/semgrep.d.ts.map +1 -0
  45. package/dist/scanners/semgrep.js +175 -0
  46. package/dist/scanners/semgrep.js.map +1 -0
  47. package/dist/types.d.ts +522 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +194 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +50 -0
@@ -0,0 +1,378 @@
1
+ /**
2
+ * Complexity Scanner
3
+ *
4
+ * Analyzes code complexity using various metrics
5
+ * Covers: complexity, dead-code, duplication categories
6
+ */
7
+ import { exec } from 'child_process';
8
+ import { promisify } from 'util';
9
+ import { readFileSync, readdirSync, statSync } from 'fs';
10
+ import { join, extname, relative } from 'path';
11
+ import { generateFingerprint } from '../types.js';
12
+ const execAsync = promisify(exec);
13
+ export class ComplexityScanner {
14
+ name = 'complexity';
15
+ categories = ['complexity', 'quality'];
16
+ // Thresholds
17
+ maxFileLines = 500;
18
+ maxFunctionLines = 50;
19
+ maxCyclomaticComplexity = 15;
20
+ maxCognitiveComplexity = 20;
21
+ // Supported extensions
22
+ supportedExtensions = ['.js', '.jsx', '.ts', '.tsx', '.py', '.rb', '.php', '.java', '.cs', '.go'];
23
+ async isAvailable() {
24
+ return true; // Built-in analysis, always available
25
+ }
26
+ async scan(target, config) {
27
+ const startTime = Date.now();
28
+ try {
29
+ const files = this.collectFiles(target.path, target);
30
+ const findings = [];
31
+ for (const file of files) {
32
+ const fileFindings = await this.analyzeFile(file, target.path);
33
+ findings.push(...fileFindings);
34
+ }
35
+ return {
36
+ scanner: this.name,
37
+ success: true,
38
+ findings,
39
+ metrics: {
40
+ duration: Date.now() - startTime,
41
+ filesScanned: files.length
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
+ collectFiles(dir, target) {
56
+ const files = [];
57
+ const excludePatterns = [
58
+ 'node_modules', 'vendor', '.git', 'dist', 'build',
59
+ '__pycache__', '.venv', 'venv', 'coverage', '.next',
60
+ ...(target.exclude || [])
61
+ ];
62
+ const walk = (currentDir) => {
63
+ try {
64
+ const entries = readdirSync(currentDir);
65
+ for (const entry of entries) {
66
+ const fullPath = join(currentDir, entry);
67
+ // Skip excluded patterns
68
+ if (excludePatterns.some(p => entry === p || fullPath.includes(`/${p}/`))) {
69
+ continue;
70
+ }
71
+ try {
72
+ const stat = statSync(fullPath);
73
+ if (stat.isDirectory()) {
74
+ walk(fullPath);
75
+ }
76
+ else if (stat.isFile()) {
77
+ const ext = extname(entry).toLowerCase();
78
+ if (this.supportedExtensions.includes(ext)) {
79
+ files.push(fullPath);
80
+ }
81
+ }
82
+ }
83
+ catch {
84
+ // Skip files we can't stat
85
+ }
86
+ }
87
+ }
88
+ catch {
89
+ // Skip directories we can't read
90
+ }
91
+ };
92
+ walk(dir);
93
+ return files;
94
+ }
95
+ async analyzeFile(filePath, basePath) {
96
+ const findings = [];
97
+ const relativePath = relative(basePath, filePath);
98
+ try {
99
+ const content = readFileSync(filePath, 'utf-8');
100
+ const lines = content.split('\n');
101
+ const ext = extname(filePath).toLowerCase();
102
+ // Basic line metrics
103
+ const metrics = this.calculateLineMetrics(lines, ext);
104
+ // File too long
105
+ if (metrics.codeLines > this.maxFileLines) {
106
+ findings.push(this.createFinding({
107
+ file: relativePath,
108
+ title: 'File exceeds maximum length',
109
+ description: `This file has ${metrics.codeLines} lines of code (threshold: ${this.maxFileLines}). Consider splitting it into smaller modules.`,
110
+ severity: metrics.codeLines > this.maxFileLines * 2 ? 'medium' : 'low',
111
+ category: 'complexity',
112
+ suggestion: 'Break down into smaller, focused modules. Each module should have a single responsibility.',
113
+ effort: 'medium'
114
+ }));
115
+ }
116
+ // Calculate complexity
117
+ const complexity = this.estimateCyclomaticComplexity(content, ext);
118
+ if (complexity > this.maxCyclomaticComplexity) {
119
+ findings.push(this.createFinding({
120
+ file: relativePath,
121
+ title: 'High cyclomatic complexity',
122
+ description: `Estimated cyclomatic complexity: ${complexity} (threshold: ${this.maxCyclomaticComplexity}). High complexity makes code harder to test and maintain.`,
123
+ severity: complexity > this.maxCyclomaticComplexity * 2 ? 'high' : 'medium',
124
+ category: 'complexity',
125
+ suggestion: 'Reduce complexity by extracting methods, using early returns, and simplifying conditionals.',
126
+ effort: 'medium'
127
+ }));
128
+ }
129
+ // Find long functions
130
+ const longFunctions = this.findLongFunctions(content, ext, relativePath);
131
+ findings.push(...longFunctions);
132
+ // Check for potential issues
133
+ const codeSmells = this.detectCodeSmells(content, ext, relativePath);
134
+ findings.push(...codeSmells);
135
+ }
136
+ catch {
137
+ // Skip files we can't read
138
+ }
139
+ return findings;
140
+ }
141
+ calculateLineMetrics(lines, ext) {
142
+ let codeLines = 0;
143
+ let commentLines = 0;
144
+ let blankLines = 0;
145
+ const commentPatterns = this.getCommentPatterns(ext);
146
+ let inBlockComment = false;
147
+ for (const line of lines) {
148
+ const trimmed = line.trim();
149
+ if (!trimmed) {
150
+ blankLines++;
151
+ continue;
152
+ }
153
+ // Simple block comment detection
154
+ if (commentPatterns.blockStart && trimmed.includes(commentPatterns.blockStart)) {
155
+ inBlockComment = true;
156
+ }
157
+ if (inBlockComment) {
158
+ commentLines++;
159
+ if (commentPatterns.blockEnd && trimmed.includes(commentPatterns.blockEnd)) {
160
+ inBlockComment = false;
161
+ }
162
+ continue;
163
+ }
164
+ // Line comment
165
+ if (commentPatterns.line && trimmed.startsWith(commentPatterns.line)) {
166
+ commentLines++;
167
+ continue;
168
+ }
169
+ codeLines++;
170
+ }
171
+ return {
172
+ path: '',
173
+ lines: lines.length,
174
+ codeLines,
175
+ commentLines,
176
+ blankLines,
177
+ complexity: 0,
178
+ functions: 0,
179
+ avgFunctionLength: 0,
180
+ maxFunctionLength: 0,
181
+ longFunctions: []
182
+ };
183
+ }
184
+ getCommentPatterns(ext) {
185
+ const patterns = {
186
+ '.js': { line: '//', blockStart: '/*', blockEnd: '*/' },
187
+ '.jsx': { line: '//', blockStart: '/*', blockEnd: '*/' },
188
+ '.ts': { line: '//', blockStart: '/*', blockEnd: '*/' },
189
+ '.tsx': { line: '//', blockStart: '/*', blockEnd: '*/' },
190
+ '.py': { line: '#', blockStart: '"""', blockEnd: '"""' },
191
+ '.rb': { line: '#', blockStart: '=begin', blockEnd: '=end' },
192
+ '.php': { line: '//', blockStart: '/*', blockEnd: '*/' },
193
+ '.java': { line: '//', blockStart: '/*', blockEnd: '*/' },
194
+ '.cs': { line: '//', blockStart: '/*', blockEnd: '*/' },
195
+ '.go': { line: '//', blockStart: '/*', blockEnd: '*/' }
196
+ };
197
+ return patterns[ext] || { line: '//' };
198
+ }
199
+ estimateCyclomaticComplexity(content, ext) {
200
+ // Simple estimation based on control flow keywords
201
+ let complexity = 1; // Base complexity
202
+ const patterns = [
203
+ /\bif\b/g,
204
+ /\belse\s+if\b/g,
205
+ /\bwhile\b/g,
206
+ /\bfor\b/g,
207
+ /\bforeach\b/gi,
208
+ /\bcase\b/g,
209
+ /\bcatch\b/g,
210
+ /\&\&/g,
211
+ /\|\|/g,
212
+ /\?\s*[^:]+\s*:/g // Ternary
213
+ ];
214
+ for (const pattern of patterns) {
215
+ const matches = content.match(pattern);
216
+ if (matches) {
217
+ complexity += matches.length;
218
+ }
219
+ }
220
+ return complexity;
221
+ }
222
+ findLongFunctions(content, ext, filePath) {
223
+ const findings = [];
224
+ // Simple regex-based function detection
225
+ const functionPatterns = {
226
+ '.js': [
227
+ /function\s+(\w+)\s*\([^)]*\)\s*\{/g,
228
+ /(\w+)\s*[:=]\s*(?:async\s+)?function\s*\([^)]*\)\s*\{/g,
229
+ /(\w+)\s*[:=]\s*(?:async\s+)?\([^)]*\)\s*=>\s*\{/g
230
+ ],
231
+ '.ts': [
232
+ /function\s+(\w+)\s*\([^)]*\)[^{]*\{/g,
233
+ /(\w+)\s*[:=]\s*(?:async\s+)?function\s*\([^)]*\)[^{]*\{/g,
234
+ /(\w+)\s*[:=]\s*(?:async\s+)?\([^)]*\)[^=]*=>\s*\{/g,
235
+ /(?:public|private|protected)?\s*(?:async\s+)?(\w+)\s*\([^)]*\)[^{]*\{/g
236
+ ],
237
+ '.py': [
238
+ /def\s+(\w+)\s*\([^)]*\)\s*(?:->.*)?:/g
239
+ ]
240
+ };
241
+ const patterns = functionPatterns[ext] || functionPatterns['.js'];
242
+ const lines = content.split('\n');
243
+ for (const pattern of patterns) {
244
+ let match;
245
+ while ((match = pattern.exec(content)) !== null) {
246
+ const startIndex = match.index;
247
+ const startLine = content.slice(0, startIndex).split('\n').length;
248
+ // Estimate function length by finding matching brace/indent
249
+ const functionLength = this.estimateFunctionLength(content.slice(startIndex), ext);
250
+ if (functionLength > this.maxFunctionLines) {
251
+ findings.push(this.createFinding({
252
+ file: filePath,
253
+ line: startLine,
254
+ title: `Function too long: ${match[1] || 'anonymous'}`,
255
+ description: `This function is approximately ${functionLength} lines long (threshold: ${this.maxFunctionLines}).`,
256
+ severity: functionLength > this.maxFunctionLines * 2 ? 'medium' : 'low',
257
+ category: 'complexity',
258
+ suggestion: 'Extract smaller helper functions. Each function should do one thing well.',
259
+ effort: 'easy'
260
+ }));
261
+ }
262
+ }
263
+ pattern.lastIndex = 0; // Reset regex
264
+ }
265
+ return findings;
266
+ }
267
+ estimateFunctionLength(content, ext) {
268
+ if (['.py', '.rb'].includes(ext)) {
269
+ // Indentation-based languages - count until dedent
270
+ const lines = content.split('\n');
271
+ if (lines.length < 2)
272
+ return 1;
273
+ const firstLine = lines[0];
274
+ const baseIndent = firstLine.match(/^\s*/)?.[0].length || 0;
275
+ let count = 1;
276
+ for (let i = 1; i < lines.length; i++) {
277
+ const line = lines[i];
278
+ if (!line.trim()) {
279
+ count++;
280
+ continue;
281
+ }
282
+ const indent = line.match(/^\s*/)?.[0].length || 0;
283
+ if (indent <= baseIndent && line.trim())
284
+ break;
285
+ count++;
286
+ }
287
+ return count;
288
+ }
289
+ // Brace-based languages
290
+ let braceCount = 0;
291
+ let started = false;
292
+ let lineCount = 0;
293
+ for (const char of content) {
294
+ if (char === '{') {
295
+ braceCount++;
296
+ started = true;
297
+ }
298
+ else if (char === '}') {
299
+ braceCount--;
300
+ if (started && braceCount === 0)
301
+ break;
302
+ }
303
+ else if (char === '\n') {
304
+ lineCount++;
305
+ }
306
+ }
307
+ return lineCount;
308
+ }
309
+ detectCodeSmells(content, ext, filePath) {
310
+ const findings = [];
311
+ const lines = content.split('\n');
312
+ // TODO comments
313
+ const todoPattern = /\b(TODO|FIXME|HACK|XXX|BUG)\b/gi;
314
+ lines.forEach((line, index) => {
315
+ const match = line.match(todoPattern);
316
+ if (match) {
317
+ findings.push(this.createFinding({
318
+ file: filePath,
319
+ line: index + 1,
320
+ title: `${match[0].toUpperCase()} comment found`,
321
+ description: `Code contains a ${match[0].toUpperCase()} marker: "${line.trim().slice(0, 80)}..."`,
322
+ severity: 'info',
323
+ category: 'quality',
324
+ suggestion: 'Address or create a tracking issue for this TODO item.',
325
+ effort: 'easy'
326
+ }));
327
+ }
328
+ });
329
+ // Console.log / print statements (potential debug code)
330
+ const debugPatterns = {
331
+ '.js': /console\.(log|debug|info)\(/g,
332
+ '.ts': /console\.(log|debug|info)\(/g,
333
+ '.py': /print\s*\(/g,
334
+ '.php': /var_dump\(|print_r\(/g
335
+ };
336
+ const debugPattern = debugPatterns[ext];
337
+ if (debugPattern) {
338
+ lines.forEach((line, index) => {
339
+ if (debugPattern.test(line) && !line.trim().startsWith('//') && !line.trim().startsWith('#')) {
340
+ findings.push(this.createFinding({
341
+ file: filePath,
342
+ line: index + 1,
343
+ title: 'Debug statement detected',
344
+ description: 'Debug/logging statement found that may need to be removed before production.',
345
+ severity: 'info',
346
+ category: 'quality',
347
+ suggestion: 'Remove or replace with proper logging framework.',
348
+ effort: 'trivial'
349
+ }));
350
+ debugPattern.lastIndex = 0;
351
+ }
352
+ });
353
+ }
354
+ return findings;
355
+ }
356
+ createFinding(params) {
357
+ const finding = {
358
+ id: `complexity-${params.file}-${params.line || 0}-${Date.now()}`,
359
+ source: this.name,
360
+ severity: params.severity,
361
+ category: params.category,
362
+ file: params.file,
363
+ line: params.line,
364
+ title: params.title,
365
+ description: params.description,
366
+ suggestion: params.suggestion,
367
+ fixAvailable: false,
368
+ autoFixable: false,
369
+ confidence: 'medium',
370
+ effort: params.effort,
371
+ fingerprint: ''
372
+ };
373
+ finding.fingerprint = generateFingerprint(finding);
374
+ return finding;
375
+ }
376
+ }
377
+ export default ComplexityScanner;
378
+ //# sourceMappingURL=complexity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"complexity.js","sourceRoot":"","sources":["../../src/scanners/complexity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ESLint Scanner
3
+ *
4
+ * Code quality and style scanning for JavaScript/TypeScript projects
5
+ * Covers: quality, style, security (with security plugins)
6
+ */
7
+ import { Scanner, ScanTarget, ScannerConfig, ScannerResult, FindingCategory } from '../types.js';
8
+ export declare class ESLintScanner implements Scanner {
9
+ name: string;
10
+ categories: FindingCategory[];
11
+ private securityRulePrefixes;
12
+ isAvailable(): Promise<boolean>;
13
+ scan(target: ScanTarget, config?: ScannerConfig): Promise<ScannerResult>;
14
+ private hasESLintConfig;
15
+ private runESLint;
16
+ private transformFindings;
17
+ private categorizeRule;
18
+ private mapSeverity;
19
+ }
20
+ export default ESLintScanner;
21
+ //# sourceMappingURL=eslint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint.d.ts","sourceRoot":"","sources":["../../src/scanners/eslint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EACL,OAAO,EACP,UAAU,EACV,aAAa,EACb,aAAa,EAEb,eAAe,EAGhB,MAAM,aAAa,CAAC;AAgCrB,qBAAa,aAAc,YAAW,OAAO;IAC3C,IAAI,SAAY;IAChB,UAAU,EAAE,eAAe,EAAE,CAAoC;IAGjE,OAAO,CAAC,oBAAoB,CAO1B;IAEI,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAkD9E,OAAO,CAAC,eAAe;YAgBT,SAAS;IAkCvB,OAAO,CAAC,iBAAiB;IA6CzB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,WAAW;CAcpB;AAED,eAAe,aAAa,CAAC"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * ESLint Scanner
3
+ *
4
+ * Code quality and style scanning for JavaScript/TypeScript projects
5
+ * Covers: quality, style, security (with security plugins)
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 ESLintScanner {
14
+ name = 'eslint';
15
+ categories = ['quality', 'style', 'security'];
16
+ // Security-related ESLint rule prefixes
17
+ securityRulePrefixes = [
18
+ 'security/',
19
+ '@typescript-eslint/no-unsafe',
20
+ 'no-eval',
21
+ 'no-implied-eval',
22
+ 'no-new-func',
23
+ 'no-script-url'
24
+ ];
25
+ async isAvailable() {
26
+ try {
27
+ await execAsync('npx eslint --version', { timeout: 10000 });
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ async scan(target, config) {
35
+ const startTime = Date.now();
36
+ // Check for ESLint config or package.json
37
+ const hasESLintConfig = this.hasESLintConfig(target.path);
38
+ const hasPackageJson = existsSync(join(target.path, 'package.json'));
39
+ if (!hasESLintConfig && !hasPackageJson) {
40
+ return {
41
+ scanner: this.name,
42
+ success: true,
43
+ findings: [],
44
+ metrics: { duration: Date.now() - startTime },
45
+ metadata: { skipped: true, reason: 'No ESLint config or package.json found' }
46
+ };
47
+ }
48
+ if (!await this.isAvailable()) {
49
+ return {
50
+ scanner: this.name,
51
+ success: false,
52
+ error: 'ESLint not available. Run `npm install eslint` in your project',
53
+ findings: [],
54
+ metrics: { duration: Date.now() - startTime }
55
+ };
56
+ }
57
+ try {
58
+ const findings = await this.runESLint(target);
59
+ return {
60
+ scanner: this.name,
61
+ success: true,
62
+ findings,
63
+ metrics: {
64
+ duration: Date.now() - startTime,
65
+ filesScanned: findings.length > 0 ? new Set(findings.map(f => f.file)).size : 0
66
+ }
67
+ };
68
+ }
69
+ catch (error) {
70
+ return {
71
+ scanner: this.name,
72
+ success: false,
73
+ error: error instanceof Error ? error.message : String(error),
74
+ findings: [],
75
+ metrics: { duration: Date.now() - startTime }
76
+ };
77
+ }
78
+ }
79
+ hasESLintConfig(path) {
80
+ const configFiles = [
81
+ '.eslintrc',
82
+ '.eslintrc.js',
83
+ '.eslintrc.cjs',
84
+ '.eslintrc.json',
85
+ '.eslintrc.yml',
86
+ '.eslintrc.yaml',
87
+ 'eslint.config.js',
88
+ 'eslint.config.mjs',
89
+ 'eslint.config.cjs'
90
+ ];
91
+ return configFiles.some(f => existsSync(join(path, f)));
92
+ }
93
+ async runESLint(target) {
94
+ const extensions = '--ext .js,.jsx,.ts,.tsx,.mjs,.cjs';
95
+ const ignorePattern = '--ignore-pattern "node_modules/**" --ignore-pattern "dist/**" --ignore-pattern "build/**"';
96
+ const cmd = `cd "${target.path}" && npx eslint . ${extensions} ${ignorePattern} --format json --no-error-on-unmatched-pattern 2>/dev/null || true`;
97
+ try {
98
+ const { stdout, stderr } = await execAsync(cmd, {
99
+ timeout: 180000, // 3 minutes
100
+ maxBuffer: 20 * 1024 * 1024
101
+ });
102
+ if (!stdout.trim() || stdout.trim() === '[]') {
103
+ return [];
104
+ }
105
+ const results = JSON.parse(stdout);
106
+ return this.transformFindings(results, target.path);
107
+ }
108
+ catch (error) {
109
+ // ESLint exits with 1 when there are linting errors
110
+ if (error.stdout) {
111
+ try {
112
+ const results = JSON.parse(error.stdout);
113
+ return this.transformFindings(results, target.path);
114
+ }
115
+ catch {
116
+ return [];
117
+ }
118
+ }
119
+ // Config errors etc. - just return empty
120
+ return [];
121
+ }
122
+ }
123
+ transformFindings(results, basePath) {
124
+ const findings = [];
125
+ for (const result of results) {
126
+ for (const msg of result.messages) {
127
+ if (!msg.ruleId)
128
+ continue; // Skip parsing errors without rule IDs
129
+ const category = this.categorizeRule(msg.ruleId);
130
+ const severity = this.mapSeverity(msg.severity, category);
131
+ // Make path relative
132
+ const relativePath = result.filePath.startsWith(basePath)
133
+ ? result.filePath.slice(basePath.length + 1)
134
+ : result.filePath;
135
+ const finding = {
136
+ id: `eslint-${msg.ruleId}-${relativePath}-${msg.line}`,
137
+ source: this.name,
138
+ severity,
139
+ category,
140
+ file: relativePath,
141
+ line: msg.line,
142
+ endLine: msg.endLine,
143
+ column: msg.column,
144
+ endColumn: msg.endColumn,
145
+ title: msg.ruleId,
146
+ description: msg.message,
147
+ suggestion: msg.suggestions?.[0]?.desc || (msg.fix ? 'Auto-fix available' : undefined),
148
+ fixAvailable: !!(msg.fix || msg.suggestions?.length),
149
+ autoFixable: !!msg.fix,
150
+ ruleId: msg.ruleId,
151
+ ruleUrl: `https://eslint.org/docs/rules/${msg.ruleId}`,
152
+ confidence: 'high',
153
+ effort: msg.fix ? 'trivial' : 'easy',
154
+ fingerprint: ''
155
+ };
156
+ finding.fingerprint = generateFingerprint(finding);
157
+ findings.push(finding);
158
+ }
159
+ }
160
+ return findings;
161
+ }
162
+ categorizeRule(ruleId) {
163
+ // Check if it's a security rule
164
+ if (this.securityRulePrefixes.some(prefix => ruleId.startsWith(prefix) || ruleId.includes(prefix))) {
165
+ return 'security';
166
+ }
167
+ // Style rules
168
+ const stylePatterns = [
169
+ 'indent', 'quotes', 'semi', 'comma', 'spacing', 'newline',
170
+ 'brace', 'curly', 'padding', 'wrap', 'linebreak'
171
+ ];
172
+ if (stylePatterns.some(p => ruleId.toLowerCase().includes(p))) {
173
+ return 'style';
174
+ }
175
+ // Complexity rules
176
+ if (ruleId.includes('complexity') || ruleId.includes('max-')) {
177
+ return 'complexity';
178
+ }
179
+ // Default to quality
180
+ return 'quality';
181
+ }
182
+ mapSeverity(eslintSeverity, category) {
183
+ // Security issues get elevated severity
184
+ if (category === 'security') {
185
+ return eslintSeverity === 2 ? 'high' : 'medium';
186
+ }
187
+ // Style issues are low priority
188
+ if (category === 'style') {
189
+ return 'low';
190
+ }
191
+ // Quality issues
192
+ return eslintSeverity === 2 ? 'medium' : 'low';
193
+ }
194
+ }
195
+ export default ESLintScanner;
196
+ //# sourceMappingURL=eslint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint.js","sourceRoot":"","sources":["../../src/scanners/eslint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Gitleaks Scanner
3
+ *
4
+ * Secret detection scanner using Gitleaks CLI
5
+ * Covers: secret category
6
+ */
7
+ import { Scanner, ScanTarget, ScannerConfig, ScannerResult, FindingCategory } from '../types.js';
8
+ export declare class GitleaksScanner implements Scanner {
9
+ name: string;
10
+ categories: FindingCategory[];
11
+ isAvailable(): Promise<boolean>;
12
+ scan(target: ScanTarget, config?: ScannerConfig): Promise<ScannerResult>;
13
+ private runGitleaks;
14
+ private transformFindings;
15
+ private determineSeverity;
16
+ private redactSecret;
17
+ private redactSnippet;
18
+ private getSuggestion;
19
+ }
20
+ export default GitleaksScanner;
21
+ //# sourceMappingURL=gitleaks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitleaks.d.ts","sourceRoot":"","sources":["../../src/scanners/gitleaks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,OAAO,EACP,UAAU,EACV,aAAa,EACb,aAAa,EAEb,eAAe,EAGhB,MAAM,aAAa,CAAC;AAyBrB,qBAAa,eAAgB,YAAW,OAAO;IAC7C,IAAI,SAAc;IAClB,UAAU,EAAE,eAAe,EAAE,CAAc;IAErC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;YAoChE,WAAW;IAkCzB,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,aAAa;CAYtB;AAED,eAAe,eAAe,CAAC"}