@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,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
+ }