guardrail-cli 1.0.6 → 2.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 (144) hide show
  1. package/README.md +483 -10
  2. package/dist/commands/baseline.d.ts +7 -0
  3. package/dist/commands/baseline.d.ts.map +1 -0
  4. package/dist/commands/baseline.js +79 -0
  5. package/dist/commands/baseline.js.map +1 -0
  6. package/dist/commands/cache.d.ts +13 -0
  7. package/dist/commands/cache.d.ts.map +1 -0
  8. package/dist/commands/cache.js +165 -0
  9. package/dist/commands/cache.js.map +1 -0
  10. package/dist/commands/evidence.d.ts +45 -0
  11. package/dist/commands/evidence.d.ts.map +1 -0
  12. package/dist/commands/evidence.js +197 -0
  13. package/dist/commands/evidence.js.map +1 -0
  14. package/dist/commands/index.d.ts +8 -0
  15. package/dist/commands/index.d.ts.map +1 -0
  16. package/dist/commands/index.js +15 -0
  17. package/dist/commands/index.js.map +1 -0
  18. package/dist/commands/scan-secrets.d.ts +47 -0
  19. package/dist/commands/scan-secrets.d.ts.map +1 -0
  20. package/dist/commands/scan-secrets.js +225 -0
  21. package/dist/commands/scan-secrets.js.map +1 -0
  22. package/dist/commands/scan-vulnerabilities-enhanced.d.ts +41 -0
  23. package/dist/commands/scan-vulnerabilities-enhanced.d.ts.map +1 -0
  24. package/dist/commands/scan-vulnerabilities-enhanced.js +368 -0
  25. package/dist/commands/scan-vulnerabilities-enhanced.js.map +1 -0
  26. package/dist/commands/scan-vulnerabilities-osv.d.ts +58 -0
  27. package/dist/commands/scan-vulnerabilities-osv.d.ts.map +1 -0
  28. package/dist/commands/scan-vulnerabilities-osv.js +716 -0
  29. package/dist/commands/scan-vulnerabilities-osv.js.map +1 -0
  30. package/dist/commands/scan-vulnerabilities.d.ts +32 -0
  31. package/dist/commands/scan-vulnerabilities.d.ts.map +1 -0
  32. package/dist/commands/scan-vulnerabilities.js +283 -0
  33. package/dist/commands/scan-vulnerabilities.js.map +1 -0
  34. package/dist/commands/secrets-allowlist.d.ts +7 -0
  35. package/dist/commands/secrets-allowlist.d.ts.map +1 -0
  36. package/dist/commands/secrets-allowlist.js +85 -0
  37. package/dist/commands/secrets-allowlist.js.map +1 -0
  38. package/dist/fix/applicator.d.ts +44 -0
  39. package/dist/fix/applicator.d.ts.map +1 -0
  40. package/dist/fix/applicator.js +144 -0
  41. package/dist/fix/applicator.js.map +1 -0
  42. package/dist/fix/backup.d.ts +38 -0
  43. package/dist/fix/backup.d.ts.map +1 -0
  44. package/dist/fix/backup.js +154 -0
  45. package/dist/fix/backup.js.map +1 -0
  46. package/dist/fix/engine.d.ts +55 -0
  47. package/dist/fix/engine.d.ts.map +1 -0
  48. package/dist/fix/engine.js +285 -0
  49. package/dist/fix/engine.js.map +1 -0
  50. package/dist/fix/index.d.ts +5 -0
  51. package/dist/fix/index.d.ts.map +1 -0
  52. package/dist/fix/index.js +12 -0
  53. package/dist/fix/index.js.map +1 -0
  54. package/dist/fix/interactive.d.ts +22 -0
  55. package/dist/fix/interactive.d.ts.map +1 -0
  56. package/dist/fix/interactive.js +172 -0
  57. package/dist/fix/interactive.js.map +1 -0
  58. package/dist/formatters/index.d.ts +6 -0
  59. package/dist/formatters/index.d.ts.map +1 -0
  60. package/dist/formatters/index.js +11 -0
  61. package/dist/formatters/index.js.map +1 -0
  62. package/dist/formatters/sarif-enhanced.d.ts +78 -0
  63. package/dist/formatters/sarif-enhanced.d.ts.map +1 -0
  64. package/dist/formatters/sarif-enhanced.js +144 -0
  65. package/dist/formatters/sarif-enhanced.js.map +1 -0
  66. package/dist/formatters/sarif-v2.d.ts +121 -0
  67. package/dist/formatters/sarif-v2.d.ts.map +1 -0
  68. package/dist/formatters/sarif-v2.js +356 -0
  69. package/dist/formatters/sarif-v2.js.map +1 -0
  70. package/dist/formatters/sarif.d.ts +72 -0
  71. package/dist/formatters/sarif.d.ts.map +1 -0
  72. package/dist/formatters/sarif.js +146 -0
  73. package/dist/formatters/sarif.js.map +1 -0
  74. package/dist/index.js +3362 -1397
  75. package/dist/index.js.map +1 -1
  76. package/dist/init/ci-generator.d.ts +18 -0
  77. package/dist/init/ci-generator.d.ts.map +1 -0
  78. package/dist/init/ci-generator.js +251 -0
  79. package/dist/init/ci-generator.js.map +1 -0
  80. package/dist/init/detect-framework.d.ts +15 -0
  81. package/dist/init/detect-framework.d.ts.map +1 -0
  82. package/dist/init/detect-framework.js +299 -0
  83. package/dist/init/detect-framework.js.map +1 -0
  84. package/dist/init/hooks-installer.d.ts +22 -0
  85. package/dist/init/hooks-installer.d.ts.map +1 -0
  86. package/dist/init/hooks-installer.js +302 -0
  87. package/dist/init/hooks-installer.js.map +1 -0
  88. package/dist/init/index.d.ts +8 -0
  89. package/dist/init/index.d.ts.map +1 -0
  90. package/dist/init/index.js +22 -0
  91. package/dist/init/index.js.map +1 -0
  92. package/dist/init/templates.d.ts +401 -0
  93. package/dist/init/templates.d.ts.map +1 -0
  94. package/dist/init/templates.js +240 -0
  95. package/dist/init/templates.js.map +1 -0
  96. package/dist/reality/reality-runner.d.ts +76 -0
  97. package/dist/reality/reality-runner.d.ts.map +1 -0
  98. package/dist/reality/reality-runner.js +454 -0
  99. package/dist/reality/reality-runner.js.map +1 -0
  100. package/dist/runtime/auth-utils.d.ts +43 -0
  101. package/dist/runtime/auth-utils.d.ts.map +1 -0
  102. package/dist/runtime/auth-utils.js +126 -0
  103. package/dist/runtime/auth-utils.js.map +1 -0
  104. package/dist/runtime/client.d.ts +74 -0
  105. package/dist/runtime/client.d.ts.map +1 -0
  106. package/dist/runtime/client.js +222 -0
  107. package/dist/runtime/client.js.map +1 -0
  108. package/dist/runtime/creds.d.ts +48 -0
  109. package/dist/runtime/creds.d.ts.map +1 -0
  110. package/dist/runtime/creds.js +245 -0
  111. package/dist/runtime/creds.js.map +1 -0
  112. package/dist/runtime/exit-codes.d.ts +47 -0
  113. package/dist/runtime/exit-codes.d.ts.map +1 -0
  114. package/dist/runtime/exit-codes.js +91 -0
  115. package/dist/runtime/exit-codes.js.map +1 -0
  116. package/dist/runtime/index.d.ts +9 -0
  117. package/dist/runtime/index.d.ts.map +1 -0
  118. package/dist/runtime/index.js +25 -0
  119. package/dist/runtime/index.js.map +1 -0
  120. package/dist/runtime/semver.d.ts +37 -0
  121. package/dist/runtime/semver.d.ts.map +1 -0
  122. package/dist/runtime/semver.js +110 -0
  123. package/dist/runtime/semver.js.map +1 -0
  124. package/dist/scanner/baseline.d.ts +52 -0
  125. package/dist/scanner/baseline.d.ts.map +1 -0
  126. package/dist/scanner/baseline.js +85 -0
  127. package/dist/scanner/baseline.js.map +1 -0
  128. package/dist/scanner/incremental.d.ts +30 -0
  129. package/dist/scanner/incremental.d.ts.map +1 -0
  130. package/dist/scanner/incremental.js +82 -0
  131. package/dist/scanner/incremental.js.map +1 -0
  132. package/dist/scanner/parallel.d.ts +43 -0
  133. package/dist/scanner/parallel.d.ts.map +1 -0
  134. package/dist/scanner/parallel.js +99 -0
  135. package/dist/scanner/parallel.js.map +1 -0
  136. package/dist/ui/frame.d.ts +68 -0
  137. package/dist/ui/frame.d.ts.map +1 -0
  138. package/dist/ui/frame.js +165 -0
  139. package/dist/ui/frame.js.map +1 -0
  140. package/dist/ui/index.d.ts +5 -0
  141. package/dist/ui/index.d.ts.map +1 -0
  142. package/dist/ui/index.js +16 -0
  143. package/dist/ui/index.js.map +1 -0
  144. package/package.json +42 -9
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ /**
3
+ * scan:secrets command
4
+ * Enterprise-grade secret detection with SecretsGuardian
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.scanSecrets = scanSecrets;
8
+ exports.outputSecretsResults = outputSecretsResults;
9
+ exports.registerScanSecretsCommand = registerScanSecretsCommand;
10
+ const path_1 = require("path");
11
+ const security_1 = require("@guardrail/security");
12
+ const exit_codes_1 = require("../runtime/exit-codes");
13
+ const evidence_1 = require("./evidence");
14
+ const sarif_1 = require("../formatters/sarif");
15
+ const fs_1 = require("fs");
16
+ // Color helpers
17
+ const c = {
18
+ reset: '\x1b[0m',
19
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
20
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
21
+ high: (s) => `\x1b[31m${s}\x1b[0m`,
22
+ medium: (s) => `\x1b[33m${s}\x1b[0m`,
23
+ low: (s) => `\x1b[36m${s}\x1b[0m`,
24
+ success: (s) => `\x1b[32m${s}\x1b[0m`,
25
+ info: (s) => `\x1b[34m${s}\x1b[0m`,
26
+ };
27
+ async function scanSecrets(projectPath, options) {
28
+ const guardian = new security_1.SecretsGuardian();
29
+ // Scan git history if requested
30
+ if (options.history) {
31
+ try {
32
+ const historyReport = await (0, security_1.scanGitHistory)(projectPath, 'cli-scan', guardian, {
33
+ depth: options.historyDepth || 50,
34
+ excludeTests: options.excludeTests,
35
+ minConfidence: options.minConfidence,
36
+ useCustomPatterns: !options.noCustomPatterns,
37
+ useAllowlist: !options.noAllowlist,
38
+ useContextualRisk: !options.noContextualRisk,
39
+ });
40
+ const findings = historyReport.detections.map(d => ({
41
+ type: d.secretType,
42
+ file: `${d.filePath} (commit: ${d.commitHash.substring(0, 7)})`,
43
+ line: d.location.line,
44
+ risk: d.risk,
45
+ confidence: d.confidence,
46
+ entropy: d.entropy,
47
+ match: d.maskedValue,
48
+ isTest: d.isTest,
49
+ recommendation: d.recommendation,
50
+ }));
51
+ return {
52
+ projectPath,
53
+ scanType: 'secrets-history',
54
+ filesScanned: historyReport.commitsScanned,
55
+ patterns: Array.from(new Set(findings.map(f => f.type))),
56
+ findings,
57
+ summary: {
58
+ total: findings.length,
59
+ highEntropy: findings.filter(f => f.entropy >= 4.0).length,
60
+ lowEntropy: findings.filter(f => f.entropy < 4.0).length,
61
+ byRisk: historyReport.summary.byType,
62
+ },
63
+ };
64
+ }
65
+ catch (err) {
66
+ if (err.message.includes('Not a git repository')) {
67
+ console.error(`\n ${c.high('✗')} Not a git repository. Use --history only in git repos.\n`);
68
+ process.exit(1);
69
+ }
70
+ throw err;
71
+ }
72
+ }
73
+ const report = await guardian.scanProject(projectPath, 'cli-scan', {
74
+ excludeTests: options.excludeTests,
75
+ minConfidence: options.minConfidence,
76
+ maxFileSizeBytes: 2 * 1024 * 1024,
77
+ concurrency: 8,
78
+ skipBinaryFiles: true,
79
+ useCustomPatterns: !options.noCustomPatterns,
80
+ useAllowlist: !options.noAllowlist,
81
+ useContextualRisk: !options.noContextualRisk,
82
+ });
83
+ const findings = report.detections.map(d => ({
84
+ type: d.secretType,
85
+ file: d.filePath,
86
+ line: d.location.line,
87
+ risk: d.risk,
88
+ confidence: d.confidence,
89
+ entropy: d.entropy,
90
+ match: d.maskedValue,
91
+ isTest: d.isTest,
92
+ recommendation: d.recommendation,
93
+ }));
94
+ const patternTypes = new Set(findings.map(f => f.type));
95
+ const highEntropy = findings.filter(f => f.entropy >= 4.0).length;
96
+ const lowEntropy = findings.filter(f => f.entropy < 4.0).length;
97
+ // Log performance stats if verbose
98
+ if (report.performance.customPatternsLoaded > 0) {
99
+ console.log(` ${c.info('ℹ')} Loaded ${report.performance.customPatternsLoaded} custom patterns from .guardrail/secrets.yaml`);
100
+ }
101
+ if (report.performance.allowlistSuppressed > 0) {
102
+ console.log(` ${c.info('ℹ')} Suppressed ${report.performance.allowlistSuppressed} allowlisted detections`);
103
+ }
104
+ if (report.performance.skippedLarge > 0 || report.performance.skippedBinary > 0) {
105
+ console.log(` ${c.dim(`Skipped: ${report.performance.skippedLarge} large files, ${report.performance.skippedBinary} binary files`)}`);
106
+ }
107
+ return {
108
+ projectPath,
109
+ scanType: 'secrets',
110
+ filesScanned: report.scannedFiles,
111
+ patterns: patternTypes.size > 0 ? Array.from(patternTypes) : ['API Keys', 'AWS Credentials', 'Private Keys', 'JWT Tokens', 'Database URLs'],
112
+ findings,
113
+ summary: {
114
+ total: findings.length,
115
+ highEntropy,
116
+ lowEntropy,
117
+ byRisk: report.summary.byRisk,
118
+ },
119
+ };
120
+ }
121
+ function outputSecretsResults(results, options) {
122
+ if (options.format === 'json') {
123
+ console.log(JSON.stringify(results, null, 2));
124
+ return;
125
+ }
126
+ if (options.format === 'sarif') {
127
+ const sarif = (0, sarif_1.toSarif)(results);
128
+ console.log(JSON.stringify(sarif, null, 2));
129
+ return;
130
+ }
131
+ console.log(` ${c.info('Patterns checked:')} ${results.patterns.join(', ')}\n`);
132
+ if (results.findings.length === 0) {
133
+ console.log(` ${c.success('✓')} ${c.bold('No secrets detected!')}\n`);
134
+ return;
135
+ }
136
+ const highRisk = results.findings.filter(f => f.risk === 'high').length;
137
+ const mediumRisk = results.findings.filter(f => f.risk === 'medium').length;
138
+ const lowRisk = results.findings.filter(f => f.risk === 'low').length;
139
+ const testFiles = results.findings.filter(f => f.isTest).length;
140
+ console.log(` ${c.high('⚠')} ${c.bold(`${results.findings.length} potential secrets found:`)}`);
141
+ console.log(` ${c.high('HIGH:')} ${highRisk} ${c.medium('MEDIUM:')} ${mediumRisk} ${c.low('LOW:')} ${lowRisk} ${c.dim(`(${testFiles} in test files)`)}\n`);
142
+ for (const finding of results.findings) {
143
+ const riskLabel = finding.risk === 'high' ? c.high('HIGH') :
144
+ finding.risk === 'medium' ? c.medium('MEDIUM') : c.low('LOW');
145
+ const testTag = finding.isTest ? c.dim(' [TEST]') : '';
146
+ console.log(` ${riskLabel} ${finding.type}${testTag}`);
147
+ console.log(` ${c.dim('├─')} ${c.info('File:')} ${finding.file}:${finding.line}`);
148
+ console.log(` ${c.dim('├─')} ${c.info('Confidence:')} ${(finding.confidence * 100).toFixed(0)}% ${c.dim('Entropy:')} ${finding.entropy.toFixed(1)}`);
149
+ console.log(` ${c.dim('├─')} ${c.info('Match:')} ${finding.match}`);
150
+ console.log(` ${c.dim('└─')} ${c.info('Fix:')} ${finding.recommendation?.remediation || 'Move to environment variables'}\n`);
151
+ }
152
+ }
153
+ function registerScanSecretsCommand(program, requireAuth, printLogo) {
154
+ program
155
+ .command('scan:secrets')
156
+ .description('Scan for hardcoded secrets and credentials')
157
+ .option('-p, --path <path>', 'Project path to scan', '.')
158
+ .option('-f, --format <format>', 'Output format: table, json, sarif', 'table')
159
+ .option('-o, --output <file>', 'Output file path')
160
+ .option('--exclude-tests', 'Exclude test files from scan', false)
161
+ .option('--min-confidence <number>', 'Minimum confidence threshold (0-1)')
162
+ .option('--fail-on-detection', 'Exit with error if secrets found', false)
163
+ .option('--evidence', 'Generate signed evidence pack', false)
164
+ .option('--history', 'Scan git commit history for secrets', false)
165
+ .option('--history-depth <number>', 'Number of commits to scan (default: 50)', '50')
166
+ .option('--no-custom-patterns', 'Disable custom patterns from .guardrail/secrets.yaml')
167
+ .option('--no-allowlist', 'Disable allowlist from .guardrail/secrets.allowlist')
168
+ .option('--no-contextual-risk', 'Disable contextual risk adjustment')
169
+ .action(async (opts) => {
170
+ requireAuth();
171
+ printLogo();
172
+ console.log(`\n${c.bold('🔐 SECRET DETECTION SCAN')}\n`);
173
+ const projectPath = (0, path_1.resolve)(opts.path);
174
+ const options = {
175
+ path: projectPath,
176
+ format: opts.format,
177
+ output: opts.output,
178
+ excludeTests: opts.excludeTests,
179
+ minConfidence: opts.minConfidence ? parseFloat(opts.minConfidence) : undefined,
180
+ failOnDetection: opts.failOnDetection,
181
+ evidence: opts.evidence,
182
+ history: opts.history,
183
+ historyDepth: opts.historyDepth ? parseInt(opts.historyDepth) : 50,
184
+ noCustomPatterns: opts.noCustomPatterns,
185
+ noAllowlist: opts.noAllowlist,
186
+ noContextualRisk: opts.noContextualRisk,
187
+ };
188
+ const startTime = Date.now();
189
+ let results;
190
+ try {
191
+ results = await scanSecrets(projectPath, options);
192
+ }
193
+ catch (err) {
194
+ if (err instanceof security_1.ConfigValidationError) {
195
+ console.error(`\n ${c.high('✗')} Custom patterns validation failed:\n`);
196
+ console.error(` ${err.message}\n`);
197
+ if (err.details) {
198
+ for (const detail of err.details) {
199
+ console.error(` • ${detail}`);
200
+ }
201
+ }
202
+ console.error(`\n Fix .guardrail/secrets.yaml and try again.\n`);
203
+ process.exit(1);
204
+ }
205
+ throw err;
206
+ }
207
+ const duration = Date.now() - startTime;
208
+ console.log(`\n${c.success('✓')} Secret scan complete (${(duration / 1000).toFixed(1)}s)`);
209
+ outputSecretsResults(results, options);
210
+ // Save to output file if specified
211
+ if (options.output) {
212
+ const outputData = options.format === 'sarif' ? (0, sarif_1.toSarif)(results) : results;
213
+ (0, fs_1.writeFileSync)(options.output, JSON.stringify(outputData, null, 2));
214
+ console.log(`\n ${c.success('✓')} Results saved to ${options.output}`);
215
+ }
216
+ if (options.evidence) {
217
+ await (0, evidence_1.generateEvidence)('secrets', results, projectPath);
218
+ }
219
+ if (options.failOnDetection && results.findings.length > 0) {
220
+ const exitCode = (0, exit_codes_1.getExitCodeForFindings)({ high: results.summary.byRisk?.high || 0, medium: results.summary.byRisk?.medium || 0 }, { failOnHigh: true });
221
+ (0, exit_codes_1.exitWith)(exitCode, `${results.findings.length} secrets detected`);
222
+ }
223
+ });
224
+ }
225
+ //# sourceMappingURL=scan-secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-secrets.js","sourceRoot":"","sources":["../../src/commands/scan-secrets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * scan:vulnerabilities command (Enhanced)
3
+ * Enterprise-grade vulnerability detection using real-time OSV integration
4
+ *
5
+ * Features:
6
+ * - Real-time OSV API queries with 24h caching
7
+ * - Multi-ecosystem support (npm, PyPI, RubyGems, Go)
8
+ * - CVSS scoring and vectors
9
+ * - Remediation path analysis
10
+ * - Direct vs transitive vulnerability grouping
11
+ * - SARIF output support
12
+ */
13
+ import { Command } from 'commander';
14
+ import { Ecosystem, VulnerabilityCheckResult } from '@guardrail/security/supply-chain/vulnerability-db';
15
+ export interface EnhancedVulnResult {
16
+ projectPath: string;
17
+ scanType: string;
18
+ ecosystem: Ecosystem;
19
+ packagesScanned: number;
20
+ findings: VulnerabilityCheckResult[];
21
+ summary: {
22
+ critical: number;
23
+ high: number;
24
+ medium: number;
25
+ low: number;
26
+ };
27
+ directVulnerabilities: number;
28
+ transitiveVulnerabilities: number;
29
+ cacheHitRate: number;
30
+ scanDuration: number;
31
+ }
32
+ /**
33
+ * Scan vulnerabilities with OSV integration
34
+ */
35
+ export declare function scanVulnerabilitiesEnhanced(projectPath: string, options: any): Promise<EnhancedVulnResult>;
36
+ /**
37
+ * Output enhanced vulnerability results
38
+ */
39
+ export declare function outputEnhancedVulnResults(results: EnhancedVulnResult, options: any): void;
40
+ export declare function registerScanVulnerabilitiesEnhancedCommand(program: Command, requireAuth: () => any, printLogo: () => void): void;
41
+ //# sourceMappingURL=scan-vulnerabilities-enhanced.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-vulnerabilities-enhanced.d.ts","sourceRoot":"","sources":["../../src/commands/scan-vulnerabilities-enhanced.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAyB,SAAS,EAAE,wBAAwB,EAAE,MAAM,mDAAmD,CAAC;AAe/H,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,wBAAwB,EAAE,CAAC;IACrC,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,qBAAqB,EAAE,MAAM,CAAC;IAC9B,yBAAyB,EAAE,MAAM,CAAC;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAoMD;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,GAAG,GACX,OAAO,CAAC,kBAAkB,CAAC,CAiF7B;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CA6CzF;AA6BD,wBAAgB,0CAA0C,CACxD,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,GAAG,EACtB,SAAS,EAAE,MAAM,IAAI,GACpB,IAAI,CAmCN"}
@@ -0,0 +1,368 @@
1
+ "use strict";
2
+ /**
3
+ * scan:vulnerabilities command (Enhanced)
4
+ * Enterprise-grade vulnerability detection using real-time OSV integration
5
+ *
6
+ * Features:
7
+ * - Real-time OSV API queries with 24h caching
8
+ * - Multi-ecosystem support (npm, PyPI, RubyGems, Go)
9
+ * - CVSS scoring and vectors
10
+ * - Remediation path analysis
11
+ * - Direct vs transitive vulnerability grouping
12
+ * - SARIF output support
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.scanVulnerabilitiesEnhanced = scanVulnerabilitiesEnhanced;
16
+ exports.outputEnhancedVulnResults = outputEnhancedVulnResults;
17
+ exports.registerScanVulnerabilitiesEnhancedCommand = registerScanVulnerabilitiesEnhancedCommand;
18
+ const path_1 = require("path");
19
+ const fs_1 = require("fs");
20
+ const exit_codes_1 = require("../runtime/exit-codes");
21
+ const vulnerability_db_1 = require("@guardrail/security/supply-chain/vulnerability-db");
22
+ const evidence_1 = require("./evidence");
23
+ const sarif_enhanced_1 = require("../formatters/sarif-enhanced");
24
+ const c = {
25
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
26
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
27
+ critical: (s) => `\x1b[35m${s}\x1b[0m`,
28
+ high: (s) => `\x1b[31m${s}\x1b[0m`,
29
+ medium: (s) => `\x1b[33m${s}\x1b[0m`,
30
+ low: (s) => `\x1b[36m${s}\x1b[0m`,
31
+ success: (s) => `\x1b[32m${s}\x1b[0m`,
32
+ info: (s) => `\x1b[34m${s}\x1b[0m`,
33
+ };
34
+ /**
35
+ * Detect ecosystem from project files
36
+ */
37
+ function detectEcosystems(projectPath) {
38
+ const ecosystems = [];
39
+ if ((0, fs_1.existsSync)((0, path_1.join)(projectPath, 'package.json')) ||
40
+ (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'package-lock.json')) ||
41
+ (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'pnpm-lock.yaml')) ||
42
+ (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'yarn.lock'))) {
43
+ ecosystems.push('npm');
44
+ }
45
+ if ((0, fs_1.existsSync)((0, path_1.join)(projectPath, 'requirements.txt')) ||
46
+ (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'Pipfile')) ||
47
+ (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'poetry.lock')) ||
48
+ (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'pyproject.toml'))) {
49
+ ecosystems.push('PyPI');
50
+ }
51
+ if ((0, fs_1.existsSync)((0, path_1.join)(projectPath, 'Gemfile')) ||
52
+ (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'Gemfile.lock'))) {
53
+ ecosystems.push('RubyGems');
54
+ }
55
+ if ((0, fs_1.existsSync)((0, path_1.join)(projectPath, 'go.mod')) ||
56
+ (0, fs_1.existsSync)((0, path_1.join)(projectPath, 'go.sum'))) {
57
+ ecosystems.push('Go');
58
+ }
59
+ return ecosystems;
60
+ }
61
+ /**
62
+ * Parse npm dependencies
63
+ */
64
+ function parseNpmDependencies(projectPath) {
65
+ const packages = [];
66
+ const packageJsonPath = (0, path_1.join)(projectPath, 'package.json');
67
+ if (!(0, fs_1.existsSync)(packageJsonPath))
68
+ return packages;
69
+ try {
70
+ const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, 'utf-8'));
71
+ const deps = packageJson.dependencies || {};
72
+ const devDeps = packageJson.devDependencies || {};
73
+ for (const [name, version] of Object.entries(deps)) {
74
+ const cleanVersion = String(version).replace(/^[\^~>=<]+/, '');
75
+ packages.push({ name, version: cleanVersion, ecosystem: 'npm', isDirect: true });
76
+ }
77
+ for (const [name, version] of Object.entries(devDeps)) {
78
+ const cleanVersion = String(version).replace(/^[\^~>=<]+/, '');
79
+ packages.push({ name, version: cleanVersion, ecosystem: 'npm', isDirect: true });
80
+ }
81
+ // Parse lockfile for transitive dependencies
82
+ const lockPath = (0, path_1.join)(projectPath, 'package-lock.json');
83
+ if ((0, fs_1.existsSync)(lockPath)) {
84
+ try {
85
+ const lockData = JSON.parse((0, fs_1.readFileSync)(lockPath, 'utf-8'));
86
+ const lockPackages = lockData.packages || {};
87
+ for (const [pkgPath, pkgInfo] of Object.entries(lockPackages)) {
88
+ if (typeof pkgInfo === 'object' && pkgInfo !== null) {
89
+ const info = pkgInfo;
90
+ const name = info.name || pkgPath.replace(/^node_modules\//, '');
91
+ const version = info.version;
92
+ if (name && version && !packages.find(p => p.name === name)) {
93
+ packages.push({ name, version, ecosystem: 'npm', isDirect: false });
94
+ }
95
+ }
96
+ }
97
+ }
98
+ catch {
99
+ // Lockfile parsing failed
100
+ }
101
+ }
102
+ }
103
+ catch {
104
+ // Package.json parsing failed
105
+ }
106
+ return packages;
107
+ }
108
+ /**
109
+ * Parse Python dependencies
110
+ */
111
+ function parsePythonDependencies(projectPath) {
112
+ const packages = [];
113
+ const requirementsPath = (0, path_1.join)(projectPath, 'requirements.txt');
114
+ if ((0, fs_1.existsSync)(requirementsPath)) {
115
+ try {
116
+ const content = (0, fs_1.readFileSync)(requirementsPath, 'utf-8');
117
+ const lines = content.split('\n');
118
+ for (const line of lines) {
119
+ const trimmed = line.trim();
120
+ if (!trimmed || trimmed.startsWith('#'))
121
+ continue;
122
+ const match = trimmed.match(/^([a-zA-Z0-9_-]+)(?:==|>=|<=|~=|>|<)?([\d.]+)?/);
123
+ if (match) {
124
+ const name = match[1];
125
+ const version = match[2] || 'latest';
126
+ packages.push({ name, version, ecosystem: 'PyPI', isDirect: true });
127
+ }
128
+ }
129
+ }
130
+ catch {
131
+ // Requirements.txt parsing failed
132
+ }
133
+ }
134
+ return packages;
135
+ }
136
+ /**
137
+ * Parse Ruby dependencies
138
+ */
139
+ function parseRubyDependencies(projectPath) {
140
+ const packages = [];
141
+ const gemfilePath = (0, path_1.join)(projectPath, 'Gemfile');
142
+ if ((0, fs_1.existsSync)(gemfilePath)) {
143
+ try {
144
+ const content = (0, fs_1.readFileSync)(gemfilePath, 'utf-8');
145
+ const lines = content.split('\n');
146
+ for (const line of lines) {
147
+ const trimmed = line.trim();
148
+ const match = trimmed.match(/gem\s+['"]([^'"]+)['"]\s*,?\s*['"]?([~>=<\d.]+)?['"]?/);
149
+ if (match) {
150
+ const name = match[1];
151
+ const version = match[2]?.replace(/[~>=<]/g, '') || 'latest';
152
+ packages.push({ name, version, ecosystem: 'RubyGems', isDirect: true });
153
+ }
154
+ }
155
+ }
156
+ catch {
157
+ // Gemfile parsing failed
158
+ }
159
+ }
160
+ return packages;
161
+ }
162
+ /**
163
+ * Parse Go dependencies
164
+ */
165
+ function parseGoDependencies(projectPath) {
166
+ const packages = [];
167
+ const goModPath = (0, path_1.join)(projectPath, 'go.mod');
168
+ if ((0, fs_1.existsSync)(goModPath)) {
169
+ try {
170
+ const content = (0, fs_1.readFileSync)(goModPath, 'utf-8');
171
+ const lines = content.split('\n');
172
+ let inRequire = false;
173
+ for (const line of lines) {
174
+ const trimmed = line.trim();
175
+ if (trimmed.startsWith('require (')) {
176
+ inRequire = true;
177
+ continue;
178
+ }
179
+ if (inRequire && trimmed === ')') {
180
+ inRequire = false;
181
+ continue;
182
+ }
183
+ const match = trimmed.match(/^(?:require\s+)?([^\s]+)\s+v?([\d.]+)/);
184
+ if (match) {
185
+ const name = match[1];
186
+ const version = match[2];
187
+ packages.push({ name, version, ecosystem: 'Go', isDirect: true });
188
+ }
189
+ }
190
+ }
191
+ catch {
192
+ // go.mod parsing failed
193
+ }
194
+ }
195
+ return packages;
196
+ }
197
+ /**
198
+ * Scan vulnerabilities with OSV integration
199
+ */
200
+ async function scanVulnerabilitiesEnhanced(projectPath, options) {
201
+ const startTime = Date.now();
202
+ const ecosystems = detectEcosystems(projectPath);
203
+ if (ecosystems.length === 0) {
204
+ return {
205
+ projectPath,
206
+ scanType: 'vulnerabilities',
207
+ ecosystem: 'npm',
208
+ packagesScanned: 0,
209
+ findings: [],
210
+ summary: { critical: 0, high: 0, medium: 0, low: 0 },
211
+ directVulnerabilities: 0,
212
+ transitiveVulnerabilities: 0,
213
+ cacheHitRate: 0,
214
+ scanDuration: Date.now() - startTime,
215
+ };
216
+ }
217
+ // Parse dependencies from all detected ecosystems
218
+ let allPackages = [];
219
+ for (const ecosystem of ecosystems) {
220
+ switch (ecosystem) {
221
+ case 'npm':
222
+ allPackages.push(...parseNpmDependencies(projectPath));
223
+ break;
224
+ case 'PyPI':
225
+ allPackages.push(...parsePythonDependencies(projectPath));
226
+ break;
227
+ case 'RubyGems':
228
+ allPackages.push(...parseRubyDependencies(projectPath));
229
+ break;
230
+ case 'Go':
231
+ allPackages.push(...parseGoDependencies(projectPath));
232
+ break;
233
+ }
234
+ }
235
+ // Query OSV for vulnerabilities
236
+ const db = new vulnerability_db_1.VulnerabilityDatabase();
237
+ const results = await db.checkPackages(allPackages);
238
+ // Calculate summary
239
+ const summary = {
240
+ critical: 0,
241
+ high: 0,
242
+ medium: 0,
243
+ low: 0,
244
+ };
245
+ let directVulnerabilities = 0;
246
+ let transitiveVulnerabilities = 0;
247
+ for (const result of results) {
248
+ if (result.isVulnerable) {
249
+ for (const vuln of result.vulnerabilities) {
250
+ summary[vuln.severity]++;
251
+ }
252
+ if (result.isDirect) {
253
+ directVulnerabilities += result.vulnerabilities.length;
254
+ }
255
+ else {
256
+ transitiveVulnerabilities += result.vulnerabilities.length;
257
+ }
258
+ }
259
+ }
260
+ const cacheStats = db.getCacheStats();
261
+ return {
262
+ projectPath,
263
+ scanType: 'vulnerabilities',
264
+ ecosystem: ecosystems[0],
265
+ packagesScanned: allPackages.length,
266
+ findings: results.filter(r => r.isVulnerable),
267
+ summary,
268
+ directVulnerabilities,
269
+ transitiveVulnerabilities,
270
+ cacheHitRate: cacheStats.hitRate,
271
+ scanDuration: Date.now() - startTime,
272
+ };
273
+ }
274
+ /**
275
+ * Output enhanced vulnerability results
276
+ */
277
+ function outputEnhancedVulnResults(results, options) {
278
+ if (options.format === 'json') {
279
+ console.log(JSON.stringify(results, null, 2));
280
+ return;
281
+ }
282
+ if (options.format === 'sarif') {
283
+ const sarif = (0, sarif_enhanced_1.toSarifVulnerabilitiesEnhanced)(results);
284
+ console.log(JSON.stringify(sarif, null, 2));
285
+ return;
286
+ }
287
+ console.log(`\n ${c.info('Ecosystem:')} ${results.ecosystem}`);
288
+ console.log(` ${c.info('Packages scanned:')} ${results.packagesScanned}`);
289
+ console.log(` ${c.info('Cache hit rate:')} ${(results.cacheHitRate * 100).toFixed(1)}%`);
290
+ console.log(` ${c.info('Scan duration:')} ${(results.scanDuration / 1000).toFixed(2)}s\n`);
291
+ const { summary } = results;
292
+ const total = summary.critical + summary.high + summary.medium + summary.low;
293
+ if (total === 0) {
294
+ console.log(` ${c.success('✓')} ${c.bold('No vulnerabilities found!')}\n`);
295
+ return;
296
+ }
297
+ console.log(` ${c.critical('CRITICAL')} ${summary.critical}`);
298
+ console.log(` ${c.high('HIGH')} ${summary.high}`);
299
+ console.log(` ${c.medium('MEDIUM')} ${summary.medium}`);
300
+ console.log(` ${c.low('LOW')} ${summary.low}\n`);
301
+ console.log(` ${c.info('Direct:')} ${results.directVulnerabilities} | ${c.info('Transitive:')} ${results.transitiveVulnerabilities}\n`);
302
+ // Group by direct vs transitive
303
+ const directFindings = results.findings.filter(f => f.isDirect);
304
+ const transitiveFindings = results.findings.filter(f => !f.isDirect);
305
+ if (directFindings.length > 0) {
306
+ console.log(`${c.bold(' DIRECT DEPENDENCIES:')}\n`);
307
+ outputFindingsList(directFindings);
308
+ }
309
+ if (transitiveFindings.length > 0) {
310
+ console.log(`\n${c.bold(' TRANSITIVE DEPENDENCIES:')}\n`);
311
+ outputFindingsList(transitiveFindings);
312
+ }
313
+ }
314
+ function outputFindingsList(findings) {
315
+ for (const finding of findings) {
316
+ for (const vuln of finding.vulnerabilities) {
317
+ const severityLabel = vuln.severity === 'critical' ? c.critical('CRITICAL') :
318
+ vuln.severity === 'high' ? c.high('HIGH') :
319
+ vuln.severity === 'medium' ? c.medium('MEDIUM') :
320
+ c.low('LOW');
321
+ console.log(` ${severityLabel} ${finding.package}@${finding.version}`);
322
+ console.log(` ${c.dim('├─')} ${c.info('ID:')} ${vuln.id}`);
323
+ console.log(` ${c.dim('├─')} ${c.info('Title:')} ${vuln.title}`);
324
+ if (vuln.cvssScore) {
325
+ console.log(` ${c.dim('├─')} ${c.info('CVSS:')} ${vuln.cvssScore.toFixed(1)}${vuln.cvssVector ? ` (${vuln.cvssVector})` : ''}`);
326
+ }
327
+ if (finding.remediationPath) {
328
+ const remed = finding.remediationPath;
329
+ const breakingLabel = remed.breakingChange ? c.medium(' [BREAKING]') : c.success(' [NON-BREAKING]');
330
+ console.log(` ${c.dim('└─')} ${c.info('Fix:')} ${remed.description}${breakingLabel}\n`);
331
+ }
332
+ else {
333
+ console.log(` ${c.dim('└─')} ${c.info('Fix:')} ${finding.recommendedVersion || 'No fix available'}\n`);
334
+ }
335
+ }
336
+ }
337
+ }
338
+ function registerScanVulnerabilitiesEnhancedCommand(program, requireAuth, printLogo) {
339
+ program
340
+ .command('scan:vulnerabilities')
341
+ .description('Scan dependencies for known vulnerabilities (OSV integration)')
342
+ .option('-p, --path <path>', 'Project path to scan', '.')
343
+ .option('-f, --format <format>', 'Output format: table, json, sarif', 'table')
344
+ .option('-o, --output <file>', 'Output file path')
345
+ .option('--fail-on-critical', 'Exit with error if critical vulnerabilities found', false)
346
+ .option('--fail-on-high', 'Exit with error if high+ vulnerabilities found', false)
347
+ .option('--evidence', 'Generate signed evidence pack', false)
348
+ .option('--ecosystem <ecosystem>', 'Filter by ecosystem: npm, PyPI, RubyGems, Go')
349
+ .action(async (opts) => {
350
+ requireAuth();
351
+ printLogo();
352
+ console.log(`\n${c.bold('🛡️ VULNERABILITY SCAN (OSV Integration)')}\n`);
353
+ const projectPath = (0, path_1.resolve)(opts.path);
354
+ const results = await scanVulnerabilitiesEnhanced(projectPath, opts);
355
+ console.log(`${c.success('✓')} Vulnerability scan complete`);
356
+ outputEnhancedVulnResults(results, opts);
357
+ if (opts.evidence) {
358
+ await (0, evidence_1.generateEvidence)('vulnerabilities', results, projectPath);
359
+ }
360
+ if (opts.failOnCritical && results.summary.critical > 0) {
361
+ (0, exit_codes_1.exitWith)(exit_codes_1.ExitCode.POLICY_FAIL, `${results.summary.critical} critical vulnerabilities found`);
362
+ }
363
+ if (opts.failOnHigh && (results.summary.critical + results.summary.high) > 0) {
364
+ (0, exit_codes_1.exitWith)(exit_codes_1.ExitCode.POLICY_FAIL, `${results.summary.critical + results.summary.high} high+ vulnerabilities found`);
365
+ }
366
+ });
367
+ }
368
+ //# sourceMappingURL=scan-vulnerabilities-enhanced.js.map