@vaultcompass/vault-guard 1.2.2 → 1.3.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/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.js +144 -38
- package/dist/commands/install-hook.js +4 -1
- package/dist/commands/scan.js +2 -0
- package/dist/utils/scan-utils.d.ts +10 -1
- package/dist/utils/scan-utils.js +28 -6
- package/package.json +3 -3
package/dist/commands/init.d.ts
CHANGED
|
@@ -14,6 +14,12 @@ export interface InitConflict {
|
|
|
14
14
|
path: string;
|
|
15
15
|
reason: 'exists' | 'foreign_manifest' | 'manifest_mismatch' | 'not_a_git_repository' | 'foreign_hook';
|
|
16
16
|
}
|
|
17
|
+
export interface InitAdvisory {
|
|
18
|
+
/** Detected manager that may already own pre-commit. */
|
|
19
|
+
manager: 'husky' | 'lefthook' | 'precommit';
|
|
20
|
+
path: string;
|
|
21
|
+
guidance: string;
|
|
22
|
+
}
|
|
17
23
|
export interface InitPlannedAction {
|
|
18
24
|
kind: 'create' | 'hook-install' | 'skip';
|
|
19
25
|
path: string;
|
|
@@ -26,6 +32,8 @@ export interface InitResult {
|
|
|
26
32
|
alreadyInitialized: boolean;
|
|
27
33
|
actions: InitPlannedAction[];
|
|
28
34
|
conflicts: InitConflict[];
|
|
35
|
+
/** Non-blocking tips when other hook managers are present. */
|
|
36
|
+
advisories: InitAdvisory[];
|
|
29
37
|
hook?: {
|
|
30
38
|
manager: string;
|
|
31
39
|
path?: string;
|
package/dist/commands/init.js
CHANGED
|
@@ -86,18 +86,8 @@ function hookRelativePath(cwd, hookPath) {
|
|
|
86
86
|
}
|
|
87
87
|
function foreignHookConflict(cwd, manager) {
|
|
88
88
|
const hook = new vault_guard_core_1.PreCommitHook();
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return undefined;
|
|
92
|
-
if (hook.isInstalled({ cwd, manager }))
|
|
93
|
-
return undefined;
|
|
94
|
-
const rel = hookRelativePath(cwd, hookPath);
|
|
95
|
-
if (manager === 'husky') {
|
|
96
|
-
const content = readFileIfExists(hookPath) ?? '';
|
|
97
|
-
if (content.includes('vault-guard'))
|
|
98
|
-
return undefined;
|
|
99
|
-
return { path: rel, reason: 'foreign_hook' };
|
|
100
|
-
}
|
|
89
|
+
// Manager-specific paths first — lefthook/precommit do not use getPreCommitHookPath
|
|
90
|
+
// (that helper still resolves the native hooks dir for non-husky managers).
|
|
101
91
|
if (manager === 'lefthook') {
|
|
102
92
|
const localPath = path.join(cwd, 'lefthook-local.yml');
|
|
103
93
|
if (!fs.existsSync(localPath))
|
|
@@ -116,10 +106,88 @@ function foreignHookConflict(cwd, manager) {
|
|
|
116
106
|
return undefined;
|
|
117
107
|
return { path: '.pre-commit-config.yaml', reason: 'foreign_hook' };
|
|
118
108
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
109
|
+
if (manager === 'husky') {
|
|
110
|
+
const hookPath = hook.getPreCommitHookPath(cwd, 'husky');
|
|
111
|
+
if (!fs.existsSync(hookPath))
|
|
112
|
+
return undefined;
|
|
113
|
+
if (hook.isInstalled({ cwd, manager: 'husky' }))
|
|
114
|
+
return undefined;
|
|
115
|
+
const content = readFileIfExists(hookPath) ?? '';
|
|
116
|
+
if (content.includes('vault-guard'))
|
|
117
|
+
return undefined;
|
|
118
|
+
return { path: hookRelativePath(cwd, hookPath), reason: 'foreign_hook' };
|
|
119
|
+
}
|
|
120
|
+
// native: POSIX hook and optional Windows companion
|
|
121
|
+
const hookPath = hook.getPreCommitHookPath(cwd, 'native');
|
|
122
|
+
if (fs.existsSync(hookPath) && !hook.isInstalled({ cwd, manager: 'native' })) {
|
|
123
|
+
const content = readFileIfExists(hookPath) ?? '';
|
|
124
|
+
if (content.trim().length > 0) {
|
|
125
|
+
return { path: hookRelativePath(cwd, hookPath), reason: 'foreign_hook' };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const cmdPath = hook.getPreCommitCmdPath(cwd);
|
|
129
|
+
if (fs.existsSync(cmdPath)) {
|
|
130
|
+
const content = readFileIfExists(cmdPath) ?? '';
|
|
131
|
+
const isOurs = content.includes('vault-guard') && content.includes('scan --staged');
|
|
132
|
+
if (content.trim().length > 0 && !isOurs) {
|
|
133
|
+
return { path: hookRelativePath(cwd, cmdPath), reason: 'foreign_hook' };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
function detectOtherHookManagers(cwd, selected) {
|
|
139
|
+
const advisories = [];
|
|
140
|
+
const huskyDir = path.join(cwd, '.husky');
|
|
141
|
+
if (fs.existsSync(huskyDir) && selected !== 'husky') {
|
|
142
|
+
advisories.push({
|
|
143
|
+
manager: 'husky',
|
|
144
|
+
path: '.husky/',
|
|
145
|
+
guidance: 'Husky detected. Prefer `vault-guard init --manager husky` or `vault-guard install-hook --manager husky` so the scan runs from .husky/pre-commit. Native hooks may not run when husky owns core.hooksPath.',
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
const lefthookYml = path.join(cwd, 'lefthook.yml');
|
|
149
|
+
const lefthookLocal = path.join(cwd, 'lefthook-local.yml');
|
|
150
|
+
if ((fs.existsSync(lefthookYml) || fs.existsSync(lefthookLocal)) && selected !== 'lefthook') {
|
|
151
|
+
advisories.push({
|
|
152
|
+
manager: 'lefthook',
|
|
153
|
+
path: fs.existsSync(lefthookLocal) ? 'lefthook-local.yml' : 'lefthook.yml',
|
|
154
|
+
guidance: 'Lefthook detected. Prefer `vault-guard init --manager lefthook` (writes lefthook-local.yml) or merge `vault-guard scan --staged` under pre-commit.commands manually. Init never overwrites existing lefthook files.',
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
const precommitCfg = path.join(cwd, '.pre-commit-config.yaml');
|
|
158
|
+
if (fs.existsSync(precommitCfg) && selected !== 'precommit') {
|
|
159
|
+
advisories.push({
|
|
160
|
+
manager: 'precommit',
|
|
161
|
+
path: '.pre-commit-config.yaml',
|
|
162
|
+
guidance: 'pre-commit framework config detected. Prefer `vault-guard init --manager precommit` only if the file is absent, or merge the local vault-guard hook into repos: yourself. Init never overwrites an existing .pre-commit-config.yaml.',
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return advisories;
|
|
166
|
+
}
|
|
167
|
+
function conflictGuidance(c) {
|
|
168
|
+
switch (c.reason) {
|
|
169
|
+
case 'exists':
|
|
170
|
+
return 'File already exists with different content — edit manually or move it aside, then re-run init.';
|
|
171
|
+
case 'foreign_manifest':
|
|
172
|
+
return 'Existing .vault-guard/init-manifest.json is invalid or foreign — fix or remove it, then re-run.';
|
|
173
|
+
case 'manifest_mismatch':
|
|
174
|
+
return 'Init manifest does not match current templates/options — run `vault-guard init --revert` then init again, or update files by hand.';
|
|
175
|
+
case 'not_a_git_repository':
|
|
176
|
+
return 'Run `git init` first, or pass `--skip-hook` to scaffold config/workflow without a hook.';
|
|
177
|
+
case 'foreign_hook':
|
|
178
|
+
if (c.path.includes('husky') || c.path.startsWith('.husky')) {
|
|
179
|
+
return 'Existing Husky pre-commit has no vault-guard stanza. Append `vault-guard scan --staged` yourself, or use `install-hook --manager husky` after reviewing the file.';
|
|
180
|
+
}
|
|
181
|
+
if (c.path.includes('lefthook')) {
|
|
182
|
+
return 'Add under pre-commit.commands:\n vault-guard:\n run: vault-guard scan --staged';
|
|
183
|
+
}
|
|
184
|
+
if (c.path.includes('pre-commit-config')) {
|
|
185
|
+
return 'Merge a local vault-guard hook into repos: (see `vault-guard install-hook --manager precommit` error output for a snippet).';
|
|
186
|
+
}
|
|
187
|
+
return 'An existing pre-commit hook is present without vault-guard. Merge `vault-guard scan --staged` manually, or remove the foreign hook if unused.';
|
|
188
|
+
default:
|
|
189
|
+
return 'Resolve manually, then re-run vault-guard init.';
|
|
190
|
+
}
|
|
123
191
|
}
|
|
124
192
|
function ensureParentDir(filePath) {
|
|
125
193
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
@@ -130,6 +198,7 @@ function planInit(options = {}) {
|
|
|
130
198
|
const manager = options.manager ?? 'native';
|
|
131
199
|
const actions = [];
|
|
132
200
|
const conflicts = [];
|
|
201
|
+
const advisories = detectOtherHookManagers(cwd, manager);
|
|
133
202
|
const trackedFiles = [];
|
|
134
203
|
const manifestAbs = path.join(cwd, templates_1.MANIFEST_RELATIVE_PATH);
|
|
135
204
|
const manifestRaw = readFileIfExists(manifestAbs);
|
|
@@ -219,17 +288,30 @@ function planInit(options = {}) {
|
|
|
219
288
|
alreadyInitialized,
|
|
220
289
|
actions,
|
|
221
290
|
conflicts,
|
|
291
|
+
advisories,
|
|
222
292
|
hook: hookState,
|
|
223
293
|
manifestPath: templates_1.MANIFEST_RELATIVE_PATH,
|
|
224
294
|
mcpMergeHint: MCP_MERGE_HINT,
|
|
225
295
|
};
|
|
226
296
|
}
|
|
227
297
|
function applyInit(plan, options = {}) {
|
|
228
|
-
if (!plan.ok || plan.dryRun
|
|
298
|
+
if (!plan.ok || plan.dryRun) {
|
|
229
299
|
return plan;
|
|
230
300
|
}
|
|
231
301
|
const cwd = options.cwd ?? process.cwd();
|
|
232
302
|
const manager = options.manager ?? 'native';
|
|
303
|
+
// Idempotent native refresh: backfill/update optional pre-commit.cmd even when
|
|
304
|
+
// the repo is already fully initialized.
|
|
305
|
+
if (plan.alreadyInitialized &&
|
|
306
|
+
plan.hook &&
|
|
307
|
+
!options.skipHook &&
|
|
308
|
+
manager === 'native') {
|
|
309
|
+
new vault_guard_core_1.PreCommitHook().install({ cwd, manager: 'native' });
|
|
310
|
+
return plan;
|
|
311
|
+
}
|
|
312
|
+
if (plan.alreadyInitialized) {
|
|
313
|
+
return plan;
|
|
314
|
+
}
|
|
233
315
|
const trackedFiles = [];
|
|
234
316
|
const createdPaths = [];
|
|
235
317
|
const rollbackCreatedFiles = () => {
|
|
@@ -244,28 +326,34 @@ function applyInit(plan, options = {}) {
|
|
|
244
326
|
}
|
|
245
327
|
}
|
|
246
328
|
};
|
|
247
|
-
if (plan.hook && !
|
|
329
|
+
if (plan.hook && !options.skipHook) {
|
|
248
330
|
const hook = new vault_guard_core_1.PreCommitHook();
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
...plan
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
331
|
+
// Always call install for native when planning a hook: first-time write, or
|
|
332
|
+
// idempotent refresh of the optional pre-commit.cmd companion.
|
|
333
|
+
if (!plan.hook.installed || manager === 'native') {
|
|
334
|
+
const result = hook.install({ cwd, manager });
|
|
335
|
+
if (!result.success && !plan.hook.installed) {
|
|
336
|
+
return {
|
|
337
|
+
...plan,
|
|
338
|
+
ok: false,
|
|
339
|
+
actions: [
|
|
340
|
+
...plan.actions,
|
|
341
|
+
{
|
|
342
|
+
kind: 'skip',
|
|
343
|
+
path: plan.hook.path ?? 'pre-commit',
|
|
344
|
+
detail: `hook install failed: ${result.message}`,
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
if (result.success) {
|
|
350
|
+
plan.hook = {
|
|
351
|
+
manager,
|
|
352
|
+
path: result.hookPath ?? plan.hook.path,
|
|
353
|
+
installed: true,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
263
356
|
}
|
|
264
|
-
plan.hook = {
|
|
265
|
-
manager,
|
|
266
|
-
path: result.hookPath ?? plan.hook.path,
|
|
267
|
-
installed: true,
|
|
268
|
-
};
|
|
269
357
|
}
|
|
270
358
|
try {
|
|
271
359
|
for (const action of plan.actions) {
|
|
@@ -345,6 +433,7 @@ function revertInit(options = {}) {
|
|
|
345
433
|
reverted: false,
|
|
346
434
|
alreadyInitialized: false,
|
|
347
435
|
actions: [],
|
|
436
|
+
advisories: [],
|
|
348
437
|
conflicts: [{ path: templates_1.MANIFEST_RELATIVE_PATH, reason: 'foreign_manifest' }],
|
|
349
438
|
manifestPath: templates_1.MANIFEST_RELATIVE_PATH,
|
|
350
439
|
mcpMergeHint: MCP_MERGE_HINT,
|
|
@@ -358,6 +447,7 @@ function revertInit(options = {}) {
|
|
|
358
447
|
reverted: false,
|
|
359
448
|
alreadyInitialized: false,
|
|
360
449
|
actions: [],
|
|
450
|
+
advisories: [],
|
|
361
451
|
conflicts: [{ path: templates_1.MANIFEST_RELATIVE_PATH, reason: 'foreign_manifest' }],
|
|
362
452
|
manifestPath: templates_1.MANIFEST_RELATIVE_PATH,
|
|
363
453
|
mcpMergeHint: MCP_MERGE_HINT,
|
|
@@ -413,6 +503,7 @@ function revertInit(options = {}) {
|
|
|
413
503
|
reverted: !dryRun,
|
|
414
504
|
alreadyInitialized: false,
|
|
415
505
|
actions,
|
|
506
|
+
advisories: [],
|
|
416
507
|
conflicts: [],
|
|
417
508
|
manifestPath: templates_1.MANIFEST_RELATIVE_PATH,
|
|
418
509
|
mcpMergeHint: MCP_MERGE_HINT,
|
|
@@ -436,6 +527,14 @@ function printHuman(result, options) {
|
|
|
436
527
|
console.error(chalk_1.default.red.bold('❌ Init blocked — conflicts (no automatic overwrites):'));
|
|
437
528
|
for (const c of result.conflicts) {
|
|
438
529
|
console.error(chalk_1.default.white(` ${c.path}`), chalk_1.default.gray(`(${c.reason})`));
|
|
530
|
+
console.error(chalk_1.default.gray(` → ${conflictGuidance(c)}`));
|
|
531
|
+
}
|
|
532
|
+
if (result.advisories.length > 0) {
|
|
533
|
+
console.error(chalk_1.default.yellow('\nAlso noted:'));
|
|
534
|
+
for (const a of result.advisories) {
|
|
535
|
+
console.error(chalk_1.default.yellow(` [${a.manager}] ${a.path}`));
|
|
536
|
+
console.error(chalk_1.default.gray(` ${a.guidance}`));
|
|
537
|
+
}
|
|
439
538
|
}
|
|
440
539
|
console.error(chalk_1.default.gray('\nResolve manually, then re-run vault-guard init.'));
|
|
441
540
|
return;
|
|
@@ -458,6 +557,13 @@ function printHuman(result, options) {
|
|
|
458
557
|
console.log(chalk_1.default.white(` ${result.dryRun ? 'install' : 'installed'} hook (${a.detail})`));
|
|
459
558
|
}
|
|
460
559
|
}
|
|
560
|
+
if (result.advisories.length > 0) {
|
|
561
|
+
console.log(chalk_1.default.yellow('\nHook manager notes:'));
|
|
562
|
+
for (const a of result.advisories) {
|
|
563
|
+
console.log(chalk_1.default.yellow(` [${a.manager}] ${a.path}`));
|
|
564
|
+
console.log(chalk_1.default.gray(` ${a.guidance}`));
|
|
565
|
+
}
|
|
566
|
+
}
|
|
461
567
|
console.log(chalk_1.default.gray(`\n${result.mcpMergeHint}`));
|
|
462
568
|
console.log(chalk_1.default.gray(`Manifest: ${result.manifestPath}`));
|
|
463
569
|
}
|
|
@@ -473,7 +579,7 @@ async function initCommand(options = {}) {
|
|
|
473
579
|
return result.ok ? 0 : 1;
|
|
474
580
|
}
|
|
475
581
|
const plan = planInit(options);
|
|
476
|
-
const result = plan.dryRun
|
|
582
|
+
const result = plan.dryRun ? plan : applyInit(plan, options);
|
|
477
583
|
if (options.json) {
|
|
478
584
|
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
479
585
|
}
|
|
@@ -16,7 +16,10 @@ async function installHookCommand(manager = 'native') {
|
|
|
16
16
|
if (result.hookPath) {
|
|
17
17
|
console.log(chalk_1.default.gray(` Path: ${result.hookPath}`));
|
|
18
18
|
}
|
|
19
|
-
console.log(chalk_1.default.gray('\nThe hook runs `vault-guard scan --staged` before each commit (staged files only).\n'
|
|
19
|
+
console.log(chalk_1.default.gray('\nThe hook runs `vault-guard scan --staged` before each commit (staged files only).\n' +
|
|
20
|
+
(manager === 'native'
|
|
21
|
+
? 'Also writes optional pre-commit.cmd (Git for Windows still runs the POSIX pre-commit via sh).\n'
|
|
22
|
+
: '')));
|
|
20
23
|
}
|
|
21
24
|
else {
|
|
22
25
|
console.error(chalk_1.default.red('❌ Error:'), chalk_1.default.white(result.message));
|
package/dist/commands/scan.js
CHANGED
|
@@ -27,10 +27,19 @@ export interface ScanOptions {
|
|
|
27
27
|
* directory scans and staged-file scans.
|
|
28
28
|
*/
|
|
29
29
|
configIgnorePatterns?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* When true, read each path from the git index (`git show :path`) so
|
|
32
|
+
* `--staged` matches what will actually be committed — including `AD`
|
|
33
|
+
* (added in index, deleted in worktree) and partially staged files.
|
|
34
|
+
*/
|
|
35
|
+
fromGitIndex?: boolean;
|
|
36
|
+
/** Repo root for `fromGitIndex` (defaults to `process.cwd()`). */
|
|
37
|
+
cwd?: string;
|
|
30
38
|
}
|
|
31
39
|
/**
|
|
32
40
|
* Scan an explicit list of files (e.g. paths from \`git diff --cached\`).
|
|
33
|
-
*
|
|
41
|
+
* Without `fromGitIndex`, skips missing worktree paths. With `fromGitIndex`,
|
|
42
|
+
* reads staged blobs so deleted worktree files are still scanned.
|
|
34
43
|
*/
|
|
35
44
|
export declare function scanFileListAsync(files: string[], scanner: SecretScanner, options?: ScanOptions): Promise<ScanResult[]>;
|
|
36
45
|
/**
|
package/dist/utils/scan-utils.js
CHANGED
|
@@ -35,15 +35,16 @@ const BINARY_EXTENSIONS = [
|
|
|
35
35
|
];
|
|
36
36
|
/**
|
|
37
37
|
* Scan an explicit list of files (e.g. paths from \`git diff --cached\`).
|
|
38
|
-
*
|
|
38
|
+
* Without `fromGitIndex`, skips missing worktree paths. With `fromGitIndex`,
|
|
39
|
+
* reads staged blobs so deleted worktree files are still scanned.
|
|
39
40
|
*/
|
|
40
41
|
async function scanFileListAsync(files, scanner, options = {}) {
|
|
41
|
-
const { verbose = false, maxSize = MAX_FILE_SIZE, skipBinary = true, progress = false, concurrency = 10, configIgnorePatterns = [], } = options;
|
|
42
|
+
const { verbose = false, maxSize = MAX_FILE_SIZE, skipBinary = true, progress = false, concurrency = 10, configIgnorePatterns = [], fromGitIndex = false, cwd = process.cwd(), } = options;
|
|
42
43
|
// Apply config ignore patterns to the explicit file list (e.g. staged files).
|
|
43
44
|
// buildConfigIgnoreFilter matches relative to cwd so patterns like
|
|
44
45
|
// `packages/**/__tests__/**` work identically for staged and directory scans.
|
|
45
46
|
const configIgnoreTester = configIgnorePatterns.length > 0
|
|
46
|
-
? (0, vault_guard_core_1.buildConfigIgnoreFilter)(configIgnorePatterns,
|
|
47
|
+
? (0, vault_guard_core_1.buildConfigIgnoreFilter)(configIgnorePatterns, cwd)
|
|
47
48
|
: null;
|
|
48
49
|
const filteredFiles = configIgnoreTester
|
|
49
50
|
? files.filter(f => !configIgnoreTester(f))
|
|
@@ -51,6 +52,27 @@ async function scanFileListAsync(files, scanner, options = {}) {
|
|
|
51
52
|
const results = [];
|
|
52
53
|
const scanFile = async (file) => {
|
|
53
54
|
try {
|
|
55
|
+
if (fromGitIndex) {
|
|
56
|
+
const rel = path_1.default.relative(cwd, file).split(path_1.default.sep).join('/');
|
|
57
|
+
if (skipBinary && isBinaryFile(file))
|
|
58
|
+
return;
|
|
59
|
+
const content = (0, vault_guard_core_1.readGitIndexFile)(cwd, rel);
|
|
60
|
+
if (skipBinary && content.includes('\0'))
|
|
61
|
+
return;
|
|
62
|
+
const byteLen = Buffer.byteLength(content, 'utf-8');
|
|
63
|
+
if (byteLen > maxSize && verbose) {
|
|
64
|
+
console.warn(chalk_1.default.yellow(`⚠️ Large staged blob (scanning in memory):`), chalk_1.default.white(rel), chalk_1.default.gray(`(${(byteLen / 1024 / 1024).toFixed(2)}MB)`));
|
|
65
|
+
}
|
|
66
|
+
if (options.stats) {
|
|
67
|
+
options.stats.filesScanned += 1;
|
|
68
|
+
options.stats.bytesScanned += byteLen;
|
|
69
|
+
}
|
|
70
|
+
const matches = (0, vault_guard_core_1.applyPathAwareSeverity)(scanner.scanContent(content, { filePath: file }), file);
|
|
71
|
+
if (matches.length > 0) {
|
|
72
|
+
results.push({ file, matches });
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
54
76
|
if (!fs_1.default.existsSync(file))
|
|
55
77
|
return;
|
|
56
78
|
const st = await fs_1.default.promises.stat(file);
|
|
@@ -59,7 +81,7 @@ async function scanFileListAsync(files, scanner, options = {}) {
|
|
|
59
81
|
if (skipBinary && isBinaryFile(file))
|
|
60
82
|
return;
|
|
61
83
|
if (st.size > maxSize && verbose) {
|
|
62
|
-
console.warn(chalk_1.default.yellow(`⚠️ Large file (streaming line-by-line):`), chalk_1.default.white(path_1.default.relative(
|
|
84
|
+
console.warn(chalk_1.default.yellow(`⚠️ Large file (streaming line-by-line):`), chalk_1.default.white(path_1.default.relative(cwd, file)), chalk_1.default.gray(`(${(st.size / 1024 / 1024).toFixed(2)}MB)`));
|
|
63
85
|
}
|
|
64
86
|
if (options.stats) {
|
|
65
87
|
options.stats.filesScanned += 1;
|
|
@@ -77,11 +99,11 @@ async function scanFileListAsync(files, scanner, options = {}) {
|
|
|
77
99
|
options.bus.add({
|
|
78
100
|
code: 'file.read_error',
|
|
79
101
|
severity: 'error',
|
|
80
|
-
ctx: { file: path_1.default.relative(
|
|
102
|
+
ctx: { file: path_1.default.relative(cwd, file), detail: String(error) },
|
|
81
103
|
});
|
|
82
104
|
}
|
|
83
105
|
if (verbose) {
|
|
84
|
-
console.error(chalk_1.default.red('❌ Error scanning file:'), chalk_1.default.white(path_1.default.relative(
|
|
106
|
+
console.error(chalk_1.default.red('❌ Error scanning file:'), chalk_1.default.white(path_1.default.relative(cwd, file)));
|
|
85
107
|
console.error(chalk_1.default.gray(String(error)));
|
|
86
108
|
}
|
|
87
109
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaultcompass/vault-guard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Block secrets at commit and in CI. Pre-commit hooks, SARIF output, and fast staged-file scans for AI-native workflows.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"chalk": "^4.1.2",
|
|
38
38
|
"commander": "^12.0.0",
|
|
39
|
-
"@vaultcompass/vault-guard-core": "1.
|
|
40
|
-
"@vaultcompass/vault-guard-telemetry": "1.
|
|
39
|
+
"@vaultcompass/vault-guard-core": "1.3.0",
|
|
40
|
+
"@vaultcompass/vault-guard-telemetry": "1.3.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/jest": "^30.0.0",
|