@vibe-validate/cli 0.17.0-rc.7 → 0.17.0-rc.9

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.
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Secret Scanning Tool Detection and Execution
3
+ *
4
+ * Handles automatic detection and execution of secret scanning tools:
5
+ * - gitleaks (native binary, fast)
6
+ * - secretlint (npm-based, containerized-friendly)
7
+ */
8
+ import { execSync } from 'node:child_process';
9
+ import { existsSync } from 'node:fs';
10
+ import { resolve } from 'node:path';
11
+ import chalk from 'chalk';
12
+ /**
13
+ * Check if gitleaks command is available
14
+ */
15
+ export function isGitleaksAvailable() {
16
+ try {
17
+ execSync('gitleaks --version', { stdio: 'ignore' });
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ /**
25
+ * Check if gitleaks config files exist
26
+ */
27
+ export function hasGitleaksConfig(cwd = process.cwd()) {
28
+ return (existsSync(resolve(cwd, '.gitleaks.toml')) ||
29
+ existsSync(resolve(cwd, '.gitleaksignore')));
30
+ }
31
+ /**
32
+ * Check if secretlint config exists
33
+ */
34
+ export function hasSecretlintConfig(cwd = process.cwd()) {
35
+ return existsSync(resolve(cwd, '.secretlintrc.json'));
36
+ }
37
+ /**
38
+ * Detect available secret scanning tools and their configurations
39
+ */
40
+ export function detectSecretScanningTools(cwd = process.cwd()) {
41
+ const gitleaksAvailable = isGitleaksAvailable();
42
+ const gitleaksConfigured = hasGitleaksConfig(cwd);
43
+ const secretlintConfigured = hasSecretlintConfig(cwd);
44
+ return [
45
+ {
46
+ tool: 'gitleaks',
47
+ available: gitleaksAvailable,
48
+ hasConfig: gitleaksConfigured,
49
+ defaultCommand: 'gitleaks protect --staged --verbose',
50
+ },
51
+ {
52
+ tool: 'secretlint',
53
+ available: true, // Always available via npx
54
+ hasConfig: secretlintConfigured,
55
+ defaultCommand: 'npx secretlint "**/*"',
56
+ },
57
+ ];
58
+ }
59
+ /**
60
+ * Determine which tools to run based on configuration and availability
61
+ */
62
+ export function selectToolsToRun(scanCommand, cwd = process.cwd()) {
63
+ // If explicit scanCommand provided (not "autodetect"), use it
64
+ if (scanCommand && scanCommand !== 'autodetect') {
65
+ // Detect which tool the command is for
66
+ const tool = scanCommand.includes('gitleaks') ? 'gitleaks' : 'secretlint';
67
+ return [{ tool, command: scanCommand }];
68
+ }
69
+ // Autodetect mode
70
+ const tools = detectSecretScanningTools(cwd);
71
+ const toRun = [];
72
+ // Check gitleaks
73
+ const gitleaks = tools.find(t => t.tool === 'gitleaks');
74
+ if (gitleaks?.hasConfig) {
75
+ // Config exists - add to run list (will warn during execution if unavailable)
76
+ toRun.push({ tool: 'gitleaks', command: gitleaks.defaultCommand });
77
+ }
78
+ // Check secretlint
79
+ const secretlint = tools.find(t => t.tool === 'secretlint');
80
+ if (secretlint?.hasConfig) {
81
+ toRun.push({ tool: 'secretlint', command: secretlint.defaultCommand });
82
+ }
83
+ // Fallback if no config files present
84
+ if (toRun.length === 0) {
85
+ if (gitleaks?.available) {
86
+ toRun.push({ tool: 'gitleaks', command: gitleaks.defaultCommand });
87
+ }
88
+ else if (secretlint) {
89
+ // Always fallback to secretlint via npx
90
+ toRun.push({ tool: 'secretlint', command: secretlint.defaultCommand });
91
+ }
92
+ }
93
+ return toRun;
94
+ }
95
+ /**
96
+ * Run a secret scanning command
97
+ */
98
+ export function runSecretScan(tool, command, verbose = false) {
99
+ const startTime = Date.now();
100
+ // Special handling for gitleaks - check availability first
101
+ if (tool === 'gitleaks' && !isGitleaksAvailable()) {
102
+ return {
103
+ tool,
104
+ passed: true, // Don't fail, just skip
105
+ duration: Date.now() - startTime,
106
+ skipped: true,
107
+ skipReason: 'gitleaks command not available',
108
+ };
109
+ }
110
+ try {
111
+ const result = execSync(command, {
112
+ encoding: 'utf8',
113
+ stdio: 'pipe',
114
+ });
115
+ const duration = Date.now() - startTime;
116
+ return {
117
+ tool,
118
+ passed: true,
119
+ duration,
120
+ output: verbose ? result : undefined,
121
+ };
122
+ }
123
+ catch (error) {
124
+ const duration = Date.now() - startTime;
125
+ if (error && typeof error === 'object' && 'stderr' in error && 'stdout' in error) {
126
+ // Safely convert stderr/stdout to strings (may be Buffer or string from child_process)
127
+ // Handle potential undefined/null values before stringification to avoid [object Object]
128
+ const stderrValue = error.stderr;
129
+ const stdoutValue = error.stdout;
130
+ let stderr = '';
131
+ if (typeof stderrValue === 'string') {
132
+ stderr = stderrValue;
133
+ }
134
+ else if (stderrValue) {
135
+ stderr = String(stderrValue);
136
+ }
137
+ let stdout = '';
138
+ if (typeof stdoutValue === 'string') {
139
+ stdout = stdoutValue;
140
+ }
141
+ else if (stdoutValue) {
142
+ stdout = String(stdoutValue);
143
+ }
144
+ return {
145
+ tool,
146
+ passed: false,
147
+ duration,
148
+ output: stdout,
149
+ error: stderr,
150
+ };
151
+ }
152
+ return {
153
+ tool,
154
+ passed: false,
155
+ duration,
156
+ error: String(error),
157
+ };
158
+ }
159
+ }
160
+ /**
161
+ * Format tool name for display
162
+ */
163
+ export function formatToolName(tool) {
164
+ return tool === 'gitleaks' ? 'gitleaks' : 'secretlint';
165
+ }
166
+ /**
167
+ * Show performance warning if scan was slow
168
+ */
169
+ export function showPerformanceWarning(tool, duration, threshold) {
170
+ if (duration <= threshold) {
171
+ return;
172
+ }
173
+ const seconds = (duration / 1000).toFixed(1);
174
+ console.warn(chalk.yellow(`\n⚠️ Secret scanning took ${seconds}s (${formatToolName(tool)})`));
175
+ if (tool === 'secretlint') {
176
+ console.warn(chalk.gray(' Consider installing gitleaks for faster scanning:'));
177
+ console.warn(chalk.gray(' • macOS: brew install gitleaks'));
178
+ console.warn(chalk.gray(' • Linux: See https://github.com/gitleaks/gitleaks#installation'));
179
+ console.warn(chalk.gray(' • Or add explicit scanCommand in config\n'));
180
+ }
181
+ }
182
+ /**
183
+ * Show error message when secrets are detected
184
+ */
185
+ export function showSecretsDetectedError(results) {
186
+ console.error(chalk.red('\n❌ Secret scanning detected potential secrets in staged files\n'));
187
+ for (const result of results) {
188
+ if (!result.passed) {
189
+ console.error(chalk.yellow(`Tool: ${formatToolName(result.tool)}`));
190
+ if (result.output) {
191
+ console.error(result.output);
192
+ }
193
+ if (result.error) {
194
+ console.error(result.error);
195
+ }
196
+ console.error('');
197
+ }
198
+ }
199
+ console.error(chalk.blue('💡 Fix options:'));
200
+ console.error(chalk.gray(' 1. Remove secrets from staged files'));
201
+ console.error(chalk.gray(' 2. Use .gitleaksignore to mark false positives (if using gitleaks)'));
202
+ console.error(chalk.gray(' 3. Use .secretlintignore to mark false positives (if using secretlint)'));
203
+ console.error(chalk.gray(' 4. Disable scanning: set hooks.preCommit.secretScanning.enabled=false'));
204
+ }
205
+ //# sourceMappingURL=secret-scanning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-scanning.js","sourceRoot":"","sources":["../../src/utils/secret-scanning.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-validate/cli",
3
- "version": "0.17.0-rc.7",
3
+ "version": "0.17.0-rc.9",
4
4
  "description": "Command-line interface for vibe-validate validation framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -62,11 +62,11 @@
62
62
  "yaml": "^2.6.1",
63
63
  "zod": "^3.24.1",
64
64
  "zod-to-json-schema": "^3.24.6",
65
- "@vibe-validate/core": "0.17.0-rc.7",
66
- "@vibe-validate/config": "0.17.0-rc.7",
67
- "@vibe-validate/extractors": "0.17.0-rc.7",
68
- "@vibe-validate/git": "0.17.0-rc.7",
69
- "@vibe-validate/history": "0.17.0-rc.7"
65
+ "@vibe-validate/extractors": "0.17.0-rc.9",
66
+ "@vibe-validate/git": "0.17.0-rc.9",
67
+ "@vibe-validate/config": "0.17.0-rc.9",
68
+ "@vibe-validate/core": "0.17.0-rc.9",
69
+ "@vibe-validate/history": "0.17.0-rc.9"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^20.14.8",