@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.
- package/LICENSE +21 -0
- package/dist/baseline.d.ts +24 -0
- package/dist/baseline.d.ts.map +1 -0
- package/dist/baseline.js +87 -0
- package/dist/baseline.js.map +1 -0
- package/dist/config-validate.d.ts +13 -0
- package/dist/config-validate.d.ts.map +1 -0
- package/dist/config-validate.js +111 -0
- package/dist/config-validate.js.map +1 -0
- package/dist/config.d.ts +69 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +106 -0
- package/dist/config.js.map +1 -0
- package/dist/diagnostics.d.ts +64 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +59 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/errors.d.ts +63 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +98 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/match-fingerprint.d.ts +7 -0
- package/dist/match-fingerprint.d.ts.map +1 -0
- package/dist/match-fingerprint.js +28 -0
- package/dist/match-fingerprint.js.map +1 -0
- package/dist/scan-output.d.ts +65 -0
- package/dist/scan-output.d.ts.map +1 -0
- package/dist/scan-output.js +140 -0
- package/dist/scan-output.js.map +1 -0
- package/dist/scanners/index.d.ts +5 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +21 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/pre-commit-hook.d.ts +41 -0
- package/dist/scanners/pre-commit-hook.d.ts.map +1 -0
- package/dist/scanners/pre-commit-hook.js +389 -0
- package/dist/scanners/pre-commit-hook.js.map +1 -0
- package/dist/scanners/secret-scanner.d.ts +99 -0
- package/dist/scanners/secret-scanner.d.ts.map +1 -0
- package/dist/scanners/secret-scanner.js +422 -0
- package/dist/scanners/secret-scanner.js.map +1 -0
- package/dist/scanners/token-counter.d.ts +27 -0
- package/dist/scanners/token-counter.d.ts.map +1 -0
- package/dist/scanners/token-counter.js +121 -0
- package/dist/scanners/token-counter.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/entropy.d.ts +17 -0
- package/dist/utils/entropy.d.ts.map +1 -0
- package/dist/utils/entropy.js +35 -0
- package/dist/utils/entropy.js.map +1 -0
- package/dist/utils/file-utils.d.ts +39 -0
- package/dist/utils/file-utils.d.ts.map +1 -0
- package/dist/utils/file-utils.js +442 -0
- package/dist/utils/file-utils.js.map +1 -0
- package/dist/utils/git-utils.d.ts +12 -0
- package/dist/utils/git-utils.d.ts.map +1 -0
- package/dist/utils/git-utils.js +55 -0
- package/dist/utils/git-utils.js.map +1 -0
- package/dist/utils/path-severity.d.ts +17 -0
- package/dist/utils/path-severity.d.ts.map +1 -0
- package/dist/utils/path-severity.js +96 -0
- package/dist/utils/path-severity.js.map +1 -0
- package/dist/utils/placeholder.d.ts +53 -0
- package/dist/utils/placeholder.d.ts.map +1 -0
- package/dist/utils/placeholder.js +198 -0
- package/dist/utils/placeholder.js.map +1 -0
- package/dist/utils/regex-safety.d.ts +102 -0
- package/dist/utils/regex-safety.d.ts.map +1 -0
- package/dist/utils/regex-safety.js +193 -0
- package/dist/utils/regex-safety.js.map +1 -0
- package/dist/utils/scan-file.d.ts +29 -0
- package/dist/utils/scan-file.d.ts.map +1 -0
- package/dist/utils/scan-file.js +125 -0
- package/dist/utils/scan-file.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { DiagnosticBus } from '../diagnostics';
|
|
2
|
+
import { SecretScanner } from '../scanners/secret-scanner';
|
|
3
|
+
import type { SecretMatch } from '../types';
|
|
4
|
+
export interface ScanTextFileOptions {
|
|
5
|
+
maxFileBytes: number;
|
|
6
|
+
/** Skip scanning lines longer than this (UTF-16 code units, same as `String#length`). */
|
|
7
|
+
maxLineUtf16Units?: number;
|
|
8
|
+
bus?: DiagnosticBus;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Read `filePath` as UTF-8 and run {@link SecretScanner.scanContent}.
|
|
12
|
+
*
|
|
13
|
+
* Files larger than `maxFileBytes` are scanned **line-by-line** so the
|
|
14
|
+
* process does not load the entire file into memory. Multi-line secrets
|
|
15
|
+
* (e.g. PEM blocks split across lines) may be missed in that mode — the
|
|
16
|
+
* trade-off is intentional for very large text files.
|
|
17
|
+
*
|
|
18
|
+
* Line breaks are normalised to a single trailing `\n` per line for the
|
|
19
|
+
* scanner (same as {@link readline}).
|
|
20
|
+
*/
|
|
21
|
+
export declare function scanTextFileAsync(scanner: SecretScanner, filePath: string, options: ScanTextFileOptions): Promise<SecretMatch[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Synchronous variant of {@link scanTextFileAsync}. For files larger than
|
|
24
|
+
* `maxFileBytes` this path **does not** stream (it would block on a full read
|
|
25
|
+
* or require a heavy incremental decoder); callers receive an empty match list
|
|
26
|
+
* and should prefer the async API for large files.
|
|
27
|
+
*/
|
|
28
|
+
export declare function scanTextFileSync(scanner: SecretScanner, filePath: string, options: ScanTextFileOptions): SecretMatch[];
|
|
29
|
+
//# sourceMappingURL=scan-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-file.d.ts","sourceRoot":"","sources":["../../src/utils/scan-file.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAI5C,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,WAAW,EAAE,CAAC,CAiDxB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,mBAAmB,GAC3B,WAAW,EAAE,CAkBf"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.scanTextFileAsync = scanTextFileAsync;
|
|
40
|
+
exports.scanTextFileSync = scanTextFileSync;
|
|
41
|
+
const fs_1 = __importDefault(require("fs"));
|
|
42
|
+
const fs_2 = require("fs");
|
|
43
|
+
const readline = __importStar(require("readline"));
|
|
44
|
+
const path_severity_1 = require("./path-severity");
|
|
45
|
+
const DEFAULT_MAX_LINE_UTF16 = 1024 * 1024;
|
|
46
|
+
/**
|
|
47
|
+
* Read `filePath` as UTF-8 and run {@link SecretScanner.scanContent}.
|
|
48
|
+
*
|
|
49
|
+
* Files larger than `maxFileBytes` are scanned **line-by-line** so the
|
|
50
|
+
* process does not load the entire file into memory. Multi-line secrets
|
|
51
|
+
* (e.g. PEM blocks split across lines) may be missed in that mode — the
|
|
52
|
+
* trade-off is intentional for very large text files.
|
|
53
|
+
*
|
|
54
|
+
* Line breaks are normalised to a single trailing `\n` per line for the
|
|
55
|
+
* scanner (same as {@link readline}).
|
|
56
|
+
*/
|
|
57
|
+
async function scanTextFileAsync(scanner, filePath, options) {
|
|
58
|
+
const maxLine = options.maxLineUtf16Units ?? DEFAULT_MAX_LINE_UTF16;
|
|
59
|
+
const st = await fs_1.default.promises.stat(filePath);
|
|
60
|
+
if (st.size <= options.maxFileBytes) {
|
|
61
|
+
const content = await fs_1.default.promises.readFile(filePath, 'utf-8');
|
|
62
|
+
return (0, path_severity_1.applyPathAwareSeverity)(scanner.scanContent(content), filePath);
|
|
63
|
+
}
|
|
64
|
+
const raw = [];
|
|
65
|
+
let utf16Offset = 0;
|
|
66
|
+
let lineNo = 0;
|
|
67
|
+
const rl = readline.createInterface({
|
|
68
|
+
input: (0, fs_2.createReadStream)(filePath, { encoding: 'utf-8' }),
|
|
69
|
+
crlfDelay: Infinity,
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
for await (const line of rl) {
|
|
73
|
+
lineNo++;
|
|
74
|
+
if (line.length > maxLine) {
|
|
75
|
+
options.bus?.add({
|
|
76
|
+
code: 'file.line_too_long',
|
|
77
|
+
severity: 'warning',
|
|
78
|
+
ctx: {
|
|
79
|
+
file: filePath,
|
|
80
|
+
line: lineNo,
|
|
81
|
+
units: line.length,
|
|
82
|
+
max_units: maxLine,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
utf16Offset += line.length + 1;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const slice = `${line}\n`;
|
|
89
|
+
const found = scanner.scanContent(slice).map(m => ({
|
|
90
|
+
...m,
|
|
91
|
+
line: lineNo,
|
|
92
|
+
column: utf16Offset + m.column,
|
|
93
|
+
}));
|
|
94
|
+
raw.push(...found);
|
|
95
|
+
utf16Offset += line.length + 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
rl.close();
|
|
100
|
+
}
|
|
101
|
+
return (0, path_severity_1.applyPathAwareSeverity)(scanner.mergeChunkedMatches(raw), filePath);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Synchronous variant of {@link scanTextFileAsync}. For files larger than
|
|
105
|
+
* `maxFileBytes` this path **does not** stream (it would block on a full read
|
|
106
|
+
* or require a heavy incremental decoder); callers receive an empty match list
|
|
107
|
+
* and should prefer the async API for large files.
|
|
108
|
+
*/
|
|
109
|
+
function scanTextFileSync(scanner, filePath, options) {
|
|
110
|
+
const st = fs_1.default.statSync(filePath);
|
|
111
|
+
if (st.size <= options.maxFileBytes) {
|
|
112
|
+
return (0, path_severity_1.applyPathAwareSeverity)(scanner.scanContent(fs_1.default.readFileSync(filePath, 'utf-8')), filePath);
|
|
113
|
+
}
|
|
114
|
+
options.bus?.add({
|
|
115
|
+
code: 'file.too_large',
|
|
116
|
+
severity: 'warning',
|
|
117
|
+
ctx: {
|
|
118
|
+
file: filePath,
|
|
119
|
+
bytes: st.size,
|
|
120
|
+
note: 'sync_scan_requires_async_for_streaming',
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=scan-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-file.js","sourceRoot":"","sources":["../../src/utils/scan-file.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vaultcompass/vault-guard-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Core engine for Vault Guard - security scanning",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/vaultcompasshq/vault-guard.git",
|
|
16
|
+
"directory": "packages/core"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/vaultcompasshq/vault-guard/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/vaultcompasshq/vault-guard#readme",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=22.0.0",
|
|
24
|
+
"npm": ">=9.0.0",
|
|
25
|
+
"pnpm": ">=9.0.0"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"security",
|
|
29
|
+
"secret-scanner",
|
|
30
|
+
"token-counter",
|
|
31
|
+
"guardrails"
|
|
32
|
+
],
|
|
33
|
+
"author": "Vault & Compass LLC",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/jest": "^30.0.0",
|
|
37
|
+
"@types/node": "^25.9.1",
|
|
38
|
+
"jest": "^30.4.2",
|
|
39
|
+
"ts-jest": "^29.4.11",
|
|
40
|
+
"typescript": "^5.0.0"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"ignore": "^5.3.2"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsc",
|
|
47
|
+
"test": "jest",
|
|
48
|
+
"test:watch": "jest --watch",
|
|
49
|
+
"test:coverage": "jest --coverage"
|
|
50
|
+
}
|
|
51
|
+
}
|