@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
|
-
|
|
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 }],
|
package/dist/utils/file-utils.js
CHANGED
|
@@ -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
|
|
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.
|
|
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",
|