@vaultcompass/vault-guard-core 1.2.1 → 1.2.3

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.
@@ -58,7 +58,10 @@ const BUILTIN_PATTERNS = new Map([
58
58
  ['aws-secret-context', { regex: /(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY)\s*[=:]\s*["']?([a-zA-Z0-9/+]{40})/gi, severity: 'critical' }],
59
59
  ['gcp-service-account', { regex: /"type":\s*"service_account"/g, severity: 'critical' }],
60
60
  ['gcp-api-key', { regex: /AIza[a-zA-Z0-9_-]{35}/g, severity: 'critical' }],
61
- ['gcp-oauth', { regex: /[0-9]+-[a-zA-Z0-9_]{32}\.apps\.googleusercontent\.com/g, severity: 'critical' }],
61
+ // OAuth 2.0 client ID, not a secret: Google documents these as safe for
62
+ // client-side / public embedding (only the paired client *secret* is
63
+ // sensitive). Kept at low severity for visibility, not blocking.
64
+ ['gcp-oauth', { regex: /[0-9]+-[a-zA-Z0-9_]{32}\.apps\.googleusercontent\.com/g, severity: 'low' }],
62
65
  ['azure-storage', { regex: /DefaultEndpointsProtocol=https;AccountName=[^;]+;AccountKey=[A-Za-z0-9+/=]{20,}/g, severity: 'critical' }],
63
66
  // --- Database connection strings ---
64
67
  ['postgresql-url', { regex: /postgres(?:ql)?:\/\/[^:@\s]+:[^@\s]+@[^:\s/]+(?::\d+)?\/\S+/g, severity: 'critical', connectionString: true }],
@@ -173,10 +173,57 @@ function collectGitignoreChain(resolvedScan, stopAt) {
173
173
  raw.reverse();
174
174
  return raw;
175
175
  }
176
+ /**
177
+ * Recursively discover `.gitignore` files inside `root` (inclusive of `root`
178
+ * itself), skipping directories the walk never descends into anyway
179
+ * ({@link shouldIgnoreDirectory}) so this pre-pass stays cheap. Scanning from
180
+ * an ancestor of a nested `.gitignore` (e.g. `vault-guard scan .` in a repo
181
+ * with a per-package `.gitignore`) otherwise never sees that file: the ignore
182
+ * filter was only ever built from ancestors of the scan root, not descendants.
183
+ */
184
+ function collectDescendantGitignores(root) {
185
+ const found = [];
186
+ const stack = [root];
187
+ while (stack.length > 0) {
188
+ const dir = stack.pop();
189
+ let entries;
190
+ try {
191
+ entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
192
+ }
193
+ catch {
194
+ continue;
195
+ }
196
+ for (const entry of entries) {
197
+ if (entry.isSymbolicLink())
198
+ continue;
199
+ const full = path_1.default.join(dir, entry.name);
200
+ if (entry.isDirectory()) {
201
+ if (shouldIgnoreDirectory(entry.name))
202
+ continue;
203
+ stack.push(full);
204
+ }
205
+ else if (entry.isFile() && entry.name === '.gitignore') {
206
+ try {
207
+ found.push({ dir, absGitignore: full, content: fs_1.default.readFileSync(full, 'utf-8') });
208
+ }
209
+ catch {
210
+ /* unreadable .gitignore — treat as absent */
211
+ }
212
+ }
213
+ }
214
+ }
215
+ // Shallow-to-deep, matching collectGitignoreChain's ordering, so more
216
+ // specific nested rules are added (and can override) after broader ones.
217
+ found.sort((a, b) => a.dir.split(path_1.default.sep).length - b.dir.split(path_1.default.sep).length);
218
+ return found;
219
+ }
176
220
  function buildIgnoreFilter(resolvedScanRoot) {
177
221
  const gitRoot = findGitRoot(resolvedScanRoot);
178
222
  const stopAt = gitRoot ?? filesystemRootFor(resolvedScanRoot);
179
- const chain = collectGitignoreChain(resolvedScanRoot, stopAt);
223
+ const ancestorChain = collectGitignoreChain(resolvedScanRoot, stopAt);
224
+ const seen = new Set(ancestorChain.map(c => c.absGitignore));
225
+ const descendantChain = collectDescendantGitignores(resolvedScanRoot).filter(c => !seen.has(c.absGitignore));
226
+ const chain = [...ancestorChain, ...descendantChain];
180
227
  const ig = (0, ignore_1.default)();
181
228
  for (const { dir, content } of chain) {
182
229
  const relDir = path_1.default.relative(stopAt, dir).split(path_1.default.sep).join('/');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaultcompass/vault-guard-core",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Secret-scanning engine: vendor-anchored patterns, entropy gating, baselines, SARIF/JSON, hook helpers.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",