@vaultcompass/vault-guard-core 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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/dist/baseline.d.ts +24 -0
  3. package/dist/baseline.d.ts.map +1 -0
  4. package/dist/baseline.js +87 -0
  5. package/dist/baseline.js.map +1 -0
  6. package/dist/config-validate.d.ts +13 -0
  7. package/dist/config-validate.d.ts.map +1 -0
  8. package/dist/config-validate.js +111 -0
  9. package/dist/config-validate.js.map +1 -0
  10. package/dist/config.d.ts +69 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +106 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/diagnostics.d.ts +64 -0
  15. package/dist/diagnostics.d.ts.map +1 -0
  16. package/dist/diagnostics.js +59 -0
  17. package/dist/diagnostics.js.map +1 -0
  18. package/dist/errors.d.ts +63 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +98 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/index.d.ts +17 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +53 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/match-fingerprint.d.ts +7 -0
  27. package/dist/match-fingerprint.d.ts.map +1 -0
  28. package/dist/match-fingerprint.js +28 -0
  29. package/dist/match-fingerprint.js.map +1 -0
  30. package/dist/scan-output.d.ts +65 -0
  31. package/dist/scan-output.d.ts.map +1 -0
  32. package/dist/scan-output.js +140 -0
  33. package/dist/scan-output.js.map +1 -0
  34. package/dist/scanners/index.d.ts +5 -0
  35. package/dist/scanners/index.d.ts.map +1 -0
  36. package/dist/scanners/index.js +21 -0
  37. package/dist/scanners/index.js.map +1 -0
  38. package/dist/scanners/pre-commit-hook.d.ts +41 -0
  39. package/dist/scanners/pre-commit-hook.d.ts.map +1 -0
  40. package/dist/scanners/pre-commit-hook.js +389 -0
  41. package/dist/scanners/pre-commit-hook.js.map +1 -0
  42. package/dist/scanners/secret-scanner.d.ts +99 -0
  43. package/dist/scanners/secret-scanner.d.ts.map +1 -0
  44. package/dist/scanners/secret-scanner.js +422 -0
  45. package/dist/scanners/secret-scanner.js.map +1 -0
  46. package/dist/scanners/token-counter.d.ts +27 -0
  47. package/dist/scanners/token-counter.d.ts.map +1 -0
  48. package/dist/scanners/token-counter.js +121 -0
  49. package/dist/scanners/token-counter.js.map +1 -0
  50. package/dist/types.d.ts +36 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +3 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/utils/entropy.d.ts +17 -0
  55. package/dist/utils/entropy.d.ts.map +1 -0
  56. package/dist/utils/entropy.js +35 -0
  57. package/dist/utils/entropy.js.map +1 -0
  58. package/dist/utils/file-utils.d.ts +39 -0
  59. package/dist/utils/file-utils.d.ts.map +1 -0
  60. package/dist/utils/file-utils.js +442 -0
  61. package/dist/utils/file-utils.js.map +1 -0
  62. package/dist/utils/git-utils.d.ts +12 -0
  63. package/dist/utils/git-utils.d.ts.map +1 -0
  64. package/dist/utils/git-utils.js +55 -0
  65. package/dist/utils/git-utils.js.map +1 -0
  66. package/dist/utils/path-severity.d.ts +17 -0
  67. package/dist/utils/path-severity.d.ts.map +1 -0
  68. package/dist/utils/path-severity.js +96 -0
  69. package/dist/utils/path-severity.js.map +1 -0
  70. package/dist/utils/placeholder.d.ts +53 -0
  71. package/dist/utils/placeholder.d.ts.map +1 -0
  72. package/dist/utils/placeholder.js +198 -0
  73. package/dist/utils/placeholder.js.map +1 -0
  74. package/dist/utils/regex-safety.d.ts +102 -0
  75. package/dist/utils/regex-safety.d.ts.map +1 -0
  76. package/dist/utils/regex-safety.js +193 -0
  77. package/dist/utils/regex-safety.js.map +1 -0
  78. package/dist/utils/scan-file.d.ts +29 -0
  79. package/dist/utils/scan-file.d.ts.map +1 -0
  80. package/dist/utils/scan-file.js +125 -0
  81. package/dist/utils/scan-file.js.map +1 -0
  82. package/package.json +51 -0
@@ -0,0 +1,422 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SecretScanner = void 0;
7
+ exports.getBuiltinPatternDocEntries = getBuiltinPatternDocEntries;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const entropy_1 = require("../utils/entropy");
10
+ const placeholder_1 = require("../utils/placeholder");
11
+ const path_severity_1 = require("../utils/path-severity");
12
+ const regex_safety_1 = require("../utils/regex-safety");
13
+ /**
14
+ * Vendor-specific patterns anchored to known prefixes / structures.
15
+ *
16
+ * Deliberately NOT included (too broad / not actual secrets):
17
+ * - cohere (`[a-zA-Z0-9]{40}`) — matches git SHAs, MD5s, …
18
+ * - aws-secret (`[a-zA-Z0-9/+]{40}`) — matches any base-64-ish string
19
+ * - circleci-token (`[a-zA-Z0-9_-]{40}`) — identical problem
20
+ * - jenkins-token (`[a-zA-Z0-9]{32}`) — matches MD5 hashes
21
+ * - kubernetes-token (JWT) — merged into jwt-token
22
+ * - elasticsearch-url (`https://u:p@h:n`) — matches any auth URL
23
+ * - ssh-rsa-public / ssh-ed25519-public — public keys are NOT secrets
24
+ * - google-analytics / google-analytics-4 — publishable measurement IDs
25
+ * - twilio-account (AC…) — public Account SID, not secret
26
+ *
27
+ * AWS secret access key is retained as a context-anchored pattern only.
28
+ */
29
+ const BUILTIN_PATTERNS = new Map([
30
+ // --- AI / ML providers ---
31
+ ['anthropic', { regex: /sk-ant-[a-zA-Z0-9_-]{20,}/g, severity: 'critical' }],
32
+ ['openai', { regex: /sk-[a-zA-Z0-9]{48}/g, severity: 'critical' }],
33
+ ['openai-project', { regex: /sk-proj-[a-zA-Z0-9_-]{48,}/g, severity: 'critical' }],
34
+ ['huggingface', { regex: /hf_[a-zA-Z0-9]{34,}/g, severity: 'critical' }],
35
+ ['replicate', { regex: /r8_[a-zA-Z0-9]{32}/g, severity: 'critical' }],
36
+ // --- Payment processors ---
37
+ ['stripe', { regex: /sk_live_[a-zA-Z0-9]{24,}/g, severity: 'critical' }],
38
+ ['stripe-test', { regex: /sk_test_[a-zA-Z0-9]{24,}/g, severity: 'high' }],
39
+ ['paypal', { regex: /access_token\$production\$[a-zA-Z0-9]{20,}/g, severity: 'critical' }],
40
+ // --- Cloud providers ---
41
+ ['aws-access', { regex: /AKIA[0-9A-Z]{16}/g, severity: 'critical' }],
42
+ // Context-anchored AWS secret: only flags values that appear on the same
43
+ // line as the canonical env-var / config-key name.
44
+ ['aws-secret-context', { regex: /(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY)\s*[=:]\s*["']?([a-zA-Z0-9/+]{40})/gi, severity: 'critical' }],
45
+ ['gcp-service-account', { regex: /"type":\s*"service_account"/g, severity: 'critical' }],
46
+ ['gcp-api-key', { regex: /AIza[a-zA-Z0-9_-]{35}/g, severity: 'critical' }],
47
+ ['gcp-oauth', { regex: /[0-9]+-[a-zA-Z0-9_]{32}\.apps\.googleusercontent\.com/g, severity: 'critical' }],
48
+ ['azure-storage', { regex: /DefaultEndpointsProtocol=https;AccountName=[^;]+;AccountKey=[A-Za-z0-9+/=]{20,}/g, severity: 'critical' }],
49
+ // --- Database connection strings ---
50
+ ['postgresql-url', { regex: /postgres(?:ql)?:\/\/[^:@\s]+:[^@\s]+@[^:\s/]+(?::\d+)?\/\S+/g, severity: 'critical', connectionString: true }],
51
+ ['mysql-url', { regex: /mysql:\/\/[^:@\s]+:[^@\s]+@[^:\s/]+(?::\d+)?\/\S+/g, severity: 'critical', connectionString: true }],
52
+ ['mongodb-url', { regex: /mongodb(?:\+srv)?:\/\/[^:@\s]+:[^@\s]+@[^:\s/]+(?::\d+)?/g, severity: 'critical', connectionString: true }],
53
+ ['redis-url', { regex: /rediss?:\/\/[^:@\s]+:[^@\s]+@[^:\s/]+(?::\d+)/g, severity: 'critical', connectionString: true }],
54
+ // --- Source control tokens ---
55
+ ['github-token', { regex: /gh[pousor]_[a-zA-Z0-9]{36}/g, severity: 'critical' }],
56
+ ['github-pat', { regex: /github_pat_[a-zA-Z0-9_]{82}/g, severity: 'critical' }],
57
+ ['gitlab-token', { regex: /glpat-[a-zA-Z0-9_-]{20}/g, severity: 'critical' }],
58
+ ['bitbucket-token', { regex: /BBDC-[a-zA-Z0-9_-]{40}/g, severity: 'critical' }],
59
+ // --- Communication platforms ---
60
+ ['slack-webhook', { regex: /hooks\.slack\.com\/services\/[A-Z0-9]{9,}\/[A-Z0-9]{9,}\/[a-zA-Z0-9]{20,}/g, severity: 'critical' }],
61
+ ['slack-token', { regex: /xox[baprs]-[a-zA-Z0-9-]{10,}/g, severity: 'critical' }],
62
+ ['discord-webhook', { regex: /discord\.com\/api\/webhooks\/[0-9]{17,20}\/[a-zA-Z0-9_-]{60,}/g, severity: 'critical' }],
63
+ // --- Email / messaging services ---
64
+ ['sendgrid-api', { regex: /SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/g, severity: 'critical' }],
65
+ ['resend-api', { regex: /re_[a-zA-Z0-9]{32,}/g, severity: 'critical' }],
66
+ ['mailgun-api', { regex: /key-[a-zA-Z0-9]{32}/g, severity: 'critical', minEntropy: 3.5 }],
67
+ // --- Package managers ---
68
+ ['npm-token', { regex: /npm_[a-zA-Z0-9]{36}/g, severity: 'critical' }],
69
+ // --- Monitoring ---
70
+ ['newrelic-api', { regex: /NRAK-[a-zA-Z0-9]{26}/g, severity: 'critical' }],
71
+ // --- E-commerce ---
72
+ ['shopify-admin', { regex: /shp(?:ss|at|ca)_[a-zA-Z0-9]{32}/g, severity: 'critical' }],
73
+ // --- Keys and auth tokens ---
74
+ ['ssh-private-key', { regex: /-----BEGIN [A-Z ]+ PRIVATE KEY-----/g, severity: 'critical' }],
75
+ ['jwt-token', { regex: /eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/g, severity: 'high' }],
76
+ // Generic patterns — entropy-gated AND placeholder-filtered (aggressive) to
77
+ // suppress false positives on documentation samples and unit-test fixtures.
78
+ ['bearer-token', { regex: /Bearer [a-zA-Z0-9_-]{20,}/g, severity: 'high', minEntropy: 3.5, aggressivePlaceholder: true }],
79
+ ['api-key-generic', { regex: /api[_-]?key["']?\s*[:=]\s*["']?([a-zA-Z0-9_-]{20,})/gi, severity: 'high', minEntropy: 3.5, aggressivePlaceholder: true }],
80
+ ['secret-generic', { regex: /secret["']?\s*[:=]\s*["']?([a-zA-Z0-9_-]{20,})/gi, severity: 'high', minEntropy: 3.5, aggressivePlaceholder: true }],
81
+ // Negative lookbehind prevents matching when `password` is a suffix of a
82
+ // compound identifier (e.g. `email-reset-password`, `changePassword`).
83
+ // Only standalone assignments trigger — `password =`, `password:`, etc.
84
+ ['password-in-code', { regex: /(?<![a-zA-Z0-9_-])password["']?\s*[:=]\s*["']([a-zA-Z0-9_\-!@#$%^&*]{12,})/gi, severity: 'high', minEntropy: 3.2, aggressivePlaceholder: true }],
85
+ ]);
86
+ /**
87
+ * Low-precision generic assignment patterns (`<key> = <value>`) whose captured
88
+ * value may be an unquoted code identifier rather than a literal secret. Only
89
+ * these are subject to the function-call suppression heuristic; vendor- and
90
+ * context-anchored detectors are deliberately excluded.
91
+ */
92
+ const GENERIC_ASSIGNMENT_IDS = new Set(['secret-generic', 'api-key-generic', 'password-in-code']);
93
+ /** Stable insertion order of {@link BUILTIN_PATTERNS}. */
94
+ function getBuiltinPatternDocEntries() {
95
+ return [...BUILTIN_PATTERNS.entries()].map(([id, entry]) => ({
96
+ id,
97
+ severity: entry.severity,
98
+ ...(entry.minEntropy !== undefined ? { minEntropy: entry.minEntropy } : {}),
99
+ regexSource: entry.regex.source,
100
+ regexFlags: entry.regex.flags,
101
+ }));
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // Severity ranking (higher = worse)
105
+ // ---------------------------------------------------------------------------
106
+ const SEVERITY_RANK = {
107
+ critical: 4,
108
+ high: 3,
109
+ medium: 2,
110
+ low: 1,
111
+ };
112
+ // ---------------------------------------------------------------------------
113
+ // SecretScanner
114
+ // ---------------------------------------------------------------------------
115
+ class SecretScanner {
116
+ patterns;
117
+ entropyThreshold;
118
+ constructor(config) {
119
+ this.entropyThreshold = config?.entropy_threshold ?? entropy_1.DEFAULT_ENTROPY_THRESHOLD;
120
+ // Start from a mutable copy of the built-ins.
121
+ this.patterns = new Map([...BUILTIN_PATTERNS].map(([k, v]) => [k, { ...v, regex: new RegExp(v.regex.source, v.regex.flags) }]));
122
+ // Apply severity overrides / "off" switches.
123
+ if (config?.severity_overrides) {
124
+ for (const [id, override] of Object.entries(config.severity_overrides)) {
125
+ if (override === 'off') {
126
+ this.patterns.delete(id);
127
+ }
128
+ else {
129
+ const entry = this.patterns.get(id);
130
+ if (entry) {
131
+ this.patterns.set(id, { ...entry, severity: override });
132
+ }
133
+ }
134
+ }
135
+ }
136
+ // Compile and append extra patterns from config.
137
+ //
138
+ // Security policy: every user-supplied regex passes through
139
+ // `validateRegexSafety` (heuristic ReDoS check). Patterns that fail are
140
+ // **not** silently skipped — that is exactly the behaviour the audit
141
+ // flagged (Audit §14: silent error swallows). They are reported via
142
+ // `extraPatternRejections` for the caller (CLI / MCP) to surface to the
143
+ // user, then dropped.
144
+ //
145
+ // `extra_patterns_unsafe: true` opts out of the heuristic, but the length
146
+ // cap still runs as a memory-use backstop.
147
+ if (config?.extra_patterns) {
148
+ const unsafe = config.extra_patterns_unsafe === true;
149
+ for (const ep of config.extra_patterns) {
150
+ const lengthCheck = (0, regex_safety_1.validateRegexLength)(ep.regex);
151
+ if (!lengthCheck.ok) {
152
+ this.extraPatternRejections.push({
153
+ id: ep.id,
154
+ reason: lengthCheck.reason ?? 'too_long',
155
+ detail: lengthCheck.detail ?? 'pattern exceeds length cap',
156
+ });
157
+ continue;
158
+ }
159
+ if (!unsafe) {
160
+ const safety = (0, regex_safety_1.validateRegexSafety)(ep.regex);
161
+ if (!safety.ok) {
162
+ this.extraPatternRejections.push({
163
+ id: ep.id,
164
+ reason: safety.reason ?? 'invalid_syntax',
165
+ detail: safety.detail ?? 'pattern failed ReDoS safety check',
166
+ });
167
+ continue;
168
+ }
169
+ }
170
+ try {
171
+ this.patterns.set(ep.id, {
172
+ regex: new RegExp(ep.regex, 'g'),
173
+ severity: ep.severity,
174
+ ...(ep.min_entropy !== undefined ? { minEntropy: ep.min_entropy } : {}),
175
+ });
176
+ }
177
+ catch (e) {
178
+ this.extraPatternRejections.push({
179
+ id: ep.id,
180
+ reason: 'invalid_syntax',
181
+ detail: e instanceof Error ? e.message : String(e),
182
+ });
183
+ }
184
+ }
185
+ }
186
+ }
187
+ /**
188
+ * Rejected `extra_patterns` from the most recent constructor call.
189
+ *
190
+ * Callers should surface these to the user (stderr today, structured
191
+ * `diagnostics[]` channel post Phase 2.2). A non-empty list means the
192
+ * user's `.vault-guard.json` declared rules that are not active.
193
+ */
194
+ extraPatternRejections = [];
195
+ /** Number of built-in + extra patterns active after config (severity "off" removes rules). */
196
+ getActivePatternCount() {
197
+ return this.patterns.size;
198
+ }
199
+ /**
200
+ * Scan a file and return deduplicated, ignore-directive-filtered matches.
201
+ */
202
+ scan(filePath) {
203
+ if (!fs_1.default.existsSync(filePath))
204
+ return [];
205
+ const content = fs_1.default.readFileSync(filePath, 'utf-8');
206
+ // Path-aware severity is applied here (not in scanContent) because it needs
207
+ // the file path. scanContent callers that know the path (scanTextFile*)
208
+ // apply it themselves, so this does not double-apply.
209
+ return (0, path_severity_1.applyPathAwareSeverity)(this.scanContent(content), filePath);
210
+ }
211
+ /**
212
+ * Scan arbitrary UTF-8 text (editor buffer, pasted snippet, MCP payload).
213
+ * Line numbers and byte offsets are relative to this string.
214
+ *
215
+ * Each call uses fresh `RegExp` instances so overlapping `scanContent` work
216
+ * (e.g. after an `await` in a concurrent worker pool) cannot corrupt
217
+ * `lastIndex` on shared patterns.
218
+ */
219
+ scanContent(content) {
220
+ const lineIndex = this.buildLineIndex(content);
221
+ const ignoredLines = this.parseIgnoreDirectives(content, lineIndex);
222
+ const raw = [];
223
+ // Fresh `RegExp` per invocation so concurrent or interleaved `scanContent`
224
+ // calls (e.g. across `await` in a worker pool) never share `lastIndex`.
225
+ const patternsForRun = new Map();
226
+ for (const [k, v] of this.patterns) {
227
+ patternsForRun.set(k, {
228
+ ...v,
229
+ regex: new RegExp(v.regex.source, v.regex.flags),
230
+ });
231
+ }
232
+ for (const [type, entry] of patternsForRun) {
233
+ const { regex, severity, minEntropy, aggressivePlaceholder, connectionString } = entry;
234
+ regex.lastIndex = 0;
235
+ let match;
236
+ while ((match = regex.exec(content)) !== null) {
237
+ const rawValue = match[1] ?? match[0];
238
+ const fullMatch = match[0];
239
+ const threshold = minEntropy ?? (minEntropy === 0 ? 0 : undefined);
240
+ if (threshold !== undefined && (0, entropy_1.shannonEntropy)(rawValue) < threshold) {
241
+ continue;
242
+ }
243
+ // Suppress documentation samples / test fixtures (e.g. AWS's
244
+ // `AKIAIOSFODNN7EXAMPLE`, `password: 'testPass1234'`). The aggressive
245
+ // tier only applies to the low-precision generic patterns.
246
+ if ((0, placeholder_1.isPlaceholderSecret)(rawValue, { aggressive: aggressivePlaceholder === true })) {
247
+ continue;
248
+ }
249
+ // Suppress local/dev/example/placeholder connection strings — the
250
+ // dominant FP source on real repos (docker-compose, `.env.example`,
251
+ // test fixtures all carry `postgres://user:pass@localhost/db`).
252
+ if (connectionString === true && (0, placeholder_1.isNonSecretConnectionString)(fullMatch)) {
253
+ continue;
254
+ }
255
+ // Suppress the ubiquitous jwt.io sample token (John Doe / sub 1234567890)
256
+ // that appears in API docs and tutorials everywhere.
257
+ if (type === 'jwt-token' && (0, placeholder_1.isSampleJwt)(fullMatch)) {
258
+ continue;
259
+ }
260
+ // Suppress unquoted assignments whose "value" is actually a function
261
+ // call — e.g. `csrf_secret = _add_new_csrf_cookie(request)`. The value
262
+ // capture group stops at `(`, so a `(` immediately following the match
263
+ // means we captured a callee identifier, not a literal secret. Scoped to
264
+ // the low-precision generic assignment patterns only — vendor-anchored
265
+ // and context-anchored detectors (incl. critical `aws-secret-context`)
266
+ // are never weakened by this heuristic.
267
+ if (GENERIC_ASSIGNMENT_IDS.has(type) &&
268
+ content[match.index + fullMatch.length] === '(') {
269
+ continue;
270
+ }
271
+ const line = this.lineFromIndex(lineIndex, match.index);
272
+ if (ignoredLines.has(line))
273
+ continue;
274
+ raw.push({
275
+ type,
276
+ value: this.maskValue(fullMatch),
277
+ line,
278
+ column: match.index,
279
+ matchLength: fullMatch.length,
280
+ severity,
281
+ });
282
+ }
283
+ }
284
+ return this.deduplicateMatches(raw);
285
+ }
286
+ /**
287
+ * Merge matches produced from chunked reads (e.g. line-by-line streaming)
288
+ * using the same overlap / severity rules as a full-file scan.
289
+ */
290
+ mergeChunkedMatches(matches) {
291
+ return this.deduplicateMatches(matches);
292
+ }
293
+ // ---------------------------------------------------------------------------
294
+ // Private helpers
295
+ // ---------------------------------------------------------------------------
296
+ /**
297
+ * Build an index of line-start byte offsets for O(log n) line lookup.
298
+ * Index position 0 = start of line 1.
299
+ */
300
+ buildLineIndex(content) {
301
+ const idx = [0];
302
+ for (let i = 0; i < content.length; i++) {
303
+ if (content[i] === '\n')
304
+ idx.push(i + 1);
305
+ }
306
+ return idx;
307
+ }
308
+ /** Binary-search the line index to return a 1-based line number. */
309
+ lineFromIndex(lineIndex, byteOffset) {
310
+ let lo = 0;
311
+ let hi = lineIndex.length - 1;
312
+ while (lo <= hi) {
313
+ const mid = (lo + hi) >>> 1;
314
+ if (lineIndex[mid] <= byteOffset)
315
+ lo = mid + 1;
316
+ else
317
+ hi = mid - 1;
318
+ }
319
+ return lo; // 1-based
320
+ }
321
+ /**
322
+ * Parse inline ignore directives from file content.
323
+ *
324
+ * Supported forms (case-insensitive):
325
+ * `// vault-guard: ignore-line` — ignores that line
326
+ * `// vault-guard: ignore-next-line` — ignores the following line
327
+ * `# vault-guard: ignore-line` — same, for shell/Python/YAML
328
+ * `# vault-guard: ignore-next-line`
329
+ *
330
+ * Returns a Set of 1-based line numbers to ignore.
331
+ */
332
+ parseIgnoreDirectives(content, lineIndex) {
333
+ const ignored = new Set();
334
+ const lines = content.split('\n');
335
+ for (let i = 0; i < lines.length; i++) {
336
+ const lineNum = i + 1; // 1-based
337
+ const lower = lines[i].toLowerCase();
338
+ if (lower.includes('vault-guard: ignore-line') || lower.includes('vault-guard:ignore-line')) {
339
+ ignored.add(lineNum);
340
+ }
341
+ if (lower.includes('vault-guard: ignore-next-line') || lower.includes('vault-guard:ignore-next-line')) {
342
+ ignored.add(lineNum + 1);
343
+ }
344
+ }
345
+ // lineIndex is available for future column-level ignore; unused here.
346
+ void lineIndex;
347
+ return ignored;
348
+ }
349
+ /**
350
+ * Deduplicate matches by overlapping byte ranges.
351
+ *
352
+ * When two matches cover the same (or overlapping) bytes in the file the
353
+ * more-specific (higher-severity or shorter) match is kept. This prevents
354
+ * the same secret from being reported multiple times when several patterns
355
+ * overlap.
356
+ */
357
+ deduplicateMatches(matches) {
358
+ if (matches.length <= 1)
359
+ return matches;
360
+ // Sort by start offset so we can do a linear sweep.
361
+ const sorted = [...matches].sort((a, b) => a.column - b.column || a.line - b.line);
362
+ const kept = [];
363
+ for (const candidate of sorted) {
364
+ const cStart = candidate.column;
365
+ const cEnd = cStart + candidate.matchLength;
366
+ let dominated = false;
367
+ for (let i = kept.length - 1; i >= 0; i--) {
368
+ const existing = kept[i];
369
+ const eStart = existing.column;
370
+ const eEnd = eStart + existing.matchLength;
371
+ // No possible overlap once we've passed the candidate start by more
372
+ // than the max pattern length (optimisation — safe upper bound: 512).
373
+ if (eEnd < cStart - 512)
374
+ break;
375
+ const overlaps = cStart < eEnd && eStart < cEnd;
376
+ if (!overlaps)
377
+ continue;
378
+ const existingRank = SEVERITY_RANK[existing.severity];
379
+ const candidateRank = SEVERITY_RANK[candidate.severity];
380
+ if (candidateRank > existingRank) {
381
+ // Candidate is more severe — replace existing.
382
+ kept.splice(i, 1);
383
+ }
384
+ else {
385
+ // Existing is at least as severe — drop candidate.
386
+ dominated = true;
387
+ break;
388
+ }
389
+ }
390
+ if (!dominated)
391
+ kept.push(candidate);
392
+ }
393
+ return kept;
394
+ }
395
+ /**
396
+ * Redact a matched secret to a low-information identifier.
397
+ *
398
+ * Format: `<prefix>…(<length>c)` — e.g. `sk-a…(37c)`.
399
+ *
400
+ * Why not show more characters?
401
+ * - 4-char prefix is enough to identify vendor (sk-a, sk_l, ghp_, AKIA, …)
402
+ * without leaking meaningful entropy of the underlying secret.
403
+ * - The exact location is already in `line` / `column`, so users don't
404
+ * need a longer fragment to find the match in source.
405
+ * - Output of this tool is routinely pasted into PRs, Slack, terminals,
406
+ * SARIF uploads, and GitHub Code Scanning — the surface area for
407
+ * leakage is large, so we keep the redaction conservative.
408
+ *
409
+ * For values shorter than 6 chars (rare; broad patterns enforce ≥20)
410
+ * we redact entirely to `*…(<length>c)`.
411
+ */
412
+ maskValue(value) {
413
+ const PREFIX = 4;
414
+ const lengthTag = `(${value.length}c)`;
415
+ if (value.length < 6) {
416
+ return `*…${lengthTag}`;
417
+ }
418
+ return `${value.substring(0, PREFIX)}…${lengthTag}`;
419
+ }
420
+ }
421
+ exports.SecretScanner = SecretScanner;
422
+ //# sourceMappingURL=secret-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-scanner.js","sourceRoot":"","sources":["../../src/scanners/secret-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { TokenReport } from '../types';
2
+ export declare class TokenCounter {
3
+ private tokenRates;
4
+ /**
5
+ * Count tokens in a file (rough estimation)
6
+ * Real implementation would use tiktoken or similar
7
+ */
8
+ countTokensInFile(filePath: string): number;
9
+ /**
10
+ * Estimate token count from text with improved accuracy
11
+ * Accounts for code density, symbols, and whitespace
12
+ */
13
+ estimateTokens(text: string): number;
14
+ /**
15
+ * Calculate cost from token usage
16
+ */
17
+ calculateCost(provider: 'anthropic' | 'openai', inputTokens: number, outputTokens: number): number;
18
+ /**
19
+ * Generate token report for a directory
20
+ */
21
+ generateReport(directoryPath: string): TokenReport;
22
+ private getAllFiles;
23
+ private shouldIgnore;
24
+ private shouldIgnoreFile;
25
+ private getExtension;
26
+ }
27
+ //# sourceMappingURL=token-counter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-counter.d.ts","sourceRoot":"","sources":["../../src/scanners/token-counter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAShB;IAEF;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAS3C;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IA+BpC;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,WAAW,GAAG,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAOlG;;OAEG;IACH,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,WAAW;IAyBlD,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,YAAY;CAIrB"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TokenCounter = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ class TokenCounter {
10
+ tokenRates = {
11
+ anthropic: {
12
+ input: 3.0, // $3 per million tokens
13
+ output: 15.0 // $15 per million tokens
14
+ },
15
+ openai: {
16
+ input: 5.0,
17
+ output: 15.0
18
+ }
19
+ };
20
+ /**
21
+ * Count tokens in a file (rough estimation)
22
+ * Real implementation would use tiktoken or similar
23
+ */
24
+ countTokensInFile(filePath) {
25
+ if (!fs_1.default.existsSync(filePath)) {
26
+ return 0;
27
+ }
28
+ const content = fs_1.default.readFileSync(filePath, 'utf-8');
29
+ return this.estimateTokens(content);
30
+ }
31
+ /**
32
+ * Estimate token count from text with improved accuracy
33
+ * Accounts for code density, symbols, and whitespace
34
+ */
35
+ estimateTokens(text) {
36
+ if (!text || text.length === 0) {
37
+ return 0;
38
+ }
39
+ // Count whitespace-separated words
40
+ const words = text.split(/\s+/).filter(w => w.length > 0);
41
+ const wordCount = words.length;
42
+ // Count symbols and operators (more common in code)
43
+ const symbolMatches = text.match(/[{}[\]();,:.<>+\-*/%=|^&!~?]/g);
44
+ const symbolCount = symbolMatches ? symbolMatches.length : 0;
45
+ // Base estimate: words + symbols (rough approximation)
46
+ let tokenEstimate = wordCount + symbolCount;
47
+ // Adjust for code density (code typically has higher token/word ratio)
48
+ // If text has many symbols relative to words, it's likely code
49
+ const symbolToWordRatio = wordCount > 0 ? symbolCount / wordCount : 0;
50
+ if (symbolToWordRatio > 0.5) {
51
+ // Code-like content: increase estimate
52
+ tokenEstimate = Math.floor(tokenEstimate * 1.3);
53
+ }
54
+ else if (symbolToWordRatio < 0.1) {
55
+ // Natural language: decrease slightly (words are better tokens)
56
+ tokenEstimate = Math.floor(tokenEstimate * 0.9);
57
+ }
58
+ // Ensure minimum estimate
59
+ return Math.max(tokenEstimate, Math.ceil(text.length / 8));
60
+ }
61
+ /**
62
+ * Calculate cost from token usage
63
+ */
64
+ calculateCost(provider, inputTokens, outputTokens) {
65
+ const rates = this.tokenRates[provider];
66
+ const inputCost = (inputTokens / 1_000_000) * rates.input;
67
+ const outputCost = (outputTokens / 1_000_000) * rates.output;
68
+ return inputCost + outputCost;
69
+ }
70
+ /**
71
+ * Generate token report for a directory
72
+ */
73
+ generateReport(directoryPath) {
74
+ let totalTokens = 0;
75
+ const breakdown = {};
76
+ const files = this.getAllFiles(directoryPath);
77
+ for (const file of files) {
78
+ const tokens = this.countTokensInFile(file);
79
+ if (tokens > 0) {
80
+ const ext = this.getExtension(file);
81
+ breakdown[ext] = (breakdown[ext] || 0) + tokens;
82
+ totalTokens += tokens;
83
+ }
84
+ }
85
+ // Estimate cost (assuming Anthropic)
86
+ const estimatedCost = (totalTokens / 1_000_000) * 3.0;
87
+ return {
88
+ totalTokens,
89
+ estimatedCost,
90
+ breakdown
91
+ };
92
+ }
93
+ getAllFiles(dirPath) {
94
+ const files = [];
95
+ const items = fs_1.default.readdirSync(dirPath);
96
+ for (const item of items) {
97
+ const fullPath = path_1.default.join(dirPath, item);
98
+ const stat = fs_1.default.statSync(fullPath);
99
+ if (stat.isDirectory() && !this.shouldIgnore(item)) {
100
+ files.push(...this.getAllFiles(fullPath));
101
+ }
102
+ else if (stat.isFile() && !this.shouldIgnoreFile(fullPath)) {
103
+ files.push(fullPath);
104
+ }
105
+ }
106
+ return files;
107
+ }
108
+ shouldIgnore(name) {
109
+ return ['node_modules', '.git', 'dist', 'build', 'coverage', '.next'].includes(name);
110
+ }
111
+ shouldIgnoreFile(filePath) {
112
+ const ext = this.getExtension(filePath);
113
+ return ['.png', '.jpg', '.jpeg', '.gif', '.pdf', '.zip', '.lock', '.log'].includes(ext);
114
+ }
115
+ getExtension(filePath) {
116
+ const parts = filePath.split('.');
117
+ return parts.length > 1 ? `.${parts[parts.length - 1]}` : '(no ext)';
118
+ }
119
+ }
120
+ exports.TokenCounter = TokenCounter;
121
+ //# sourceMappingURL=token-counter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-counter.js","sourceRoot":"","sources":["../../src/scanners/token-counter.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAGxB,MAAa,YAAY;IACf,UAAU,GAAG;QACnB,SAAS,EAAE;YACT,KAAK,EAAE,GAAG,EAAE,wBAAwB;YACpC,MAAM,EAAE,IAAI,CAAC,yBAAyB;SACvC;QACD,MAAM,EAAE;YACN,KAAK,EAAE,GAAG;YACV,MAAM,EAAE,IAAI;SACb;KACF,CAAC;IAEF;;;OAGG;IACH,iBAAiB,CAAC,QAAgB;QAChC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,OAAO,GAAG,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,IAAY;QACzB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,CAAC;QACX,CAAC;QAED,mCAAmC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;QAE/B,oDAAoD;QACpD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7D,uDAAuD;QACvD,IAAI,aAAa,GAAG,SAAS,GAAG,WAAW,CAAC;QAE5C,uEAAuE;QACvE,+DAA+D;QAC/D,MAAM,iBAAiB,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACtE,IAAI,iBAAiB,GAAG,GAAG,EAAE,CAAC;YAC5B,uCAAuC;YACvC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,iBAAiB,GAAG,GAAG,EAAE,CAAC;YACnC,gEAAgE;YAChE,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC;QAClD,CAAC;QAED,0BAA0B;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAgC,EAAE,WAAmB,EAAE,YAAoB;QACvF,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1D,MAAM,UAAU,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QAC7D,OAAO,SAAS,GAAG,UAAU,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,aAAqB;QAClC,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,MAAM,SAAS,GAA2B,EAAE,CAAC;QAE7C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAE9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;gBACpC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC;gBAChD,WAAW,IAAI,MAAM,CAAC;YACxB,CAAC;QACH,CAAC;QAED,qCAAqC;QACrC,MAAM,aAAa,GAAG,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC;QAEtD,OAAO;YACL,WAAW;YACX,aAAa;YACb,SAAS;SACV,CAAC;IACJ,CAAC;IAEO,WAAW,CAAC,OAAe;QACjC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,YAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAEtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC1C,MAAM,IAAI,GAAG,YAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEnC,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC5C,CAAC;iBAAM,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7D,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,YAAY,CAAC,IAAY;QAC/B,OAAO,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvF,CAAC;IAEO,gBAAgB,CAAC,QAAgB;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACxC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC1F,CAAC;IAEO,YAAY,CAAC,QAAgB;QACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;IACvE,CAAC;CACF;AAjID,oCAiIC"}
@@ -0,0 +1,36 @@
1
+ export interface SecretMatch {
2
+ /** Pattern id (e.g. "anthropic", "aws-access"). */
3
+ type: string;
4
+ /** Masked representation of the matched value (safe to log). */
5
+ value: string;
6
+ /** 1-based line number in the file. */
7
+ line: number;
8
+ /** 0-based absolute byte offset in the file (used for deduplication). */
9
+ column: number;
10
+ /** Byte length of the original match (used for SARIF region output). */
11
+ matchLength: number;
12
+ severity: 'critical' | 'high' | 'medium' | 'low';
13
+ }
14
+ export interface TokenReport {
15
+ totalTokens: number;
16
+ estimatedCost: number;
17
+ breakdown: Record<string, number>;
18
+ }
19
+ export interface GuardStatus {
20
+ security: {
21
+ clean: boolean;
22
+ critical: number;
23
+ warning: number;
24
+ };
25
+ tokens: {
26
+ used: number;
27
+ limit: number;
28
+ cost: number;
29
+ };
30
+ savings: {
31
+ percentage: number;
32
+ amount: number;
33
+ };
34
+ aiActive: boolean;
35
+ }
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CAClD;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE;QACR,KAAK,EAAE,OAAO,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC;CACnB"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}