(ctx)
| 451 | } |
| 452 | |
| 453 | export const commandFn: TypedGunshiCommandFn<typeof commandSpec> = async (ctx) => { |
| 454 | // Handle --install-hook before doing any scanning |
| 455 | if (ctx.values['install-hook']) { |
| 456 | await installHook(process.cwd()); |
| 457 | return; |
| 458 | } |
| 459 | |
| 460 | const onlyStaged = ctx.values.staged ?? false; |
| 461 | const includeIgnored = ctx.values['include-ignored'] ?? false; |
| 462 | |
| 463 | // Positional arguments are treated as explicit paths/globs to scan |
| 464 | const scanTargets = ctx.values.targets ?? []; |
| 465 | |
| 466 | // Load the varlock env graph to get the actual sensitive values |
| 467 | const envGraph = await loadVarlockEnvGraph({ |
| 468 | entryFilePaths: ctx.values.path, |
| 469 | }); |
| 470 | |
| 471 | // Check for loading/schema errors |
| 472 | for (const source of envGraph.sortedDataSources) { |
| 473 | if (source.loadingError) { |
| 474 | throw new CliExitError(`Error loading config: ${source.loadingError.message}`, { |
| 475 | suggestion: 'Make sure your .env.schema file is valid.', |
| 476 | }); |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | await envGraph.resolveEnvValues(); |
| 481 | |
| 482 | // Collect all sensitive string values that are non-empty |
| 483 | const sensitiveValues = new Map<string, string>(); |
| 484 | for (const itemKey in envGraph.configSchema) { |
| 485 | const item = envGraph.configSchema[itemKey]; |
| 486 | if (item.isSensitive && _.isString(item.resolvedValue) && item.resolvedValue !== '') { |
| 487 | sensitiveValues.set(itemKey, item.resolvedValue); |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | if (sensitiveValues.size === 0) { |
| 492 | logLines([ansis.green('✅ No sensitive values found in config - nothing to scan for.')]); |
| 493 | return; |
| 494 | } |
| 495 | |
| 496 | const cwd = process.cwd(); |
| 497 | let files: Array<string>; |
| 498 | |
| 499 | if (scanTargets.length > 0) { |
| 500 | // Explicit paths/globs provided — scan only those targets. |
| 501 | // We skip git-aware filtering so the user gets exactly what they asked for, |
| 502 | // and we do NOT apply SKIP_DIRS (e.g. `dist`, `.next`) since the whole point |
| 503 | // is often to scan a build output directory. |
| 504 | files = await resolveTargetPaths(scanTargets, cwd); |
| 505 | } else if (includeIgnored) { |
| 506 | // Walk the full directory tree, no git filtering |
| 507 | files = await walkDirectory(cwd); |
| 508 | } else { |
| 509 | // Try to use git to get non-ignored files |
| 510 | const gitFiles = await getGitFiles(cwd, onlyStaged); |
nothing calls this directly
no test coverage detected