llm-mask 0.3.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/.github/workflows/llm-mask-check.yml +62 -0
- package/LICENSE +21 -0
- package/README.md +549 -0
- package/dist/audit.d.ts +56 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +90 -0
- package/dist/audit.js.map +1 -0
- package/dist/cli-old.d.ts +12 -0
- package/dist/cli-old.d.ts.map +1 -0
- package/dist/cli-old.js +257 -0
- package/dist/cli-old.js.map +1 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +197 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.d.ts +9 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +121 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +81 -0
- package/dist/config.js.map +1 -0
- package/dist/context-detection.d.ts +54 -0
- package/dist/context-detection.d.ts.map +1 -0
- package/dist/context-detection.js +219 -0
- package/dist/context-detection.js.map +1 -0
- package/dist/diff-masking.d.ts +51 -0
- package/dist/diff-masking.d.ts.map +1 -0
- package/dist/diff-masking.js +121 -0
- package/dist/diff-masking.js.map +1 -0
- package/dist/executor.d.ts +105 -0
- package/dist/executor.d.ts.map +1 -0
- package/dist/executor.js +250 -0
- package/dist/executor.js.map +1 -0
- package/dist/executor.test.d.ts +5 -0
- package/dist/executor.test.d.ts.map +1 -0
- package/dist/executor.test.js +500 -0
- package/dist/executor.test.js.map +1 -0
- package/dist/features.test.d.ts +5 -0
- package/dist/features.test.d.ts.map +1 -0
- package/dist/features.test.js +118 -0
- package/dist/features.test.js.map +1 -0
- package/dist/formatter.d.ts +54 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +139 -0
- package/dist/formatter.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/language-patterns.d.ts +39 -0
- package/dist/language-patterns.d.ts.map +1 -0
- package/dist/language-patterns.js +177 -0
- package/dist/language-patterns.js.map +1 -0
- package/dist/masker.d.ts +100 -0
- package/dist/masker.d.ts.map +1 -0
- package/dist/masker.js +255 -0
- package/dist/masker.js.map +1 -0
- package/dist/masker.test.d.ts +11 -0
- package/dist/masker.test.d.ts.map +1 -0
- package/dist/masker.test.js +162 -0
- package/dist/masker.test.js.map +1 -0
- package/dist/mcp-server.d.ts +9 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +494 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/patterns.d.ts +25 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +184 -0
- package/dist/patterns.js.map +1 -0
- package/dist/scanner.d.ts +75 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +247 -0
- package/dist/scanner.js.map +1 -0
- package/dist/test-utils.d.ts +5 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +6 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/tokenizer.d.ts +62 -0
- package/dist/tokenizer.d.ts.map +1 -0
- package/dist/tokenizer.js +95 -0
- package/dist/tokenizer.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
package/dist/patterns.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in masking patterns
|
|
3
|
+
* These are organized by priority (higher = applied first)
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Built-in patterns for detecting sensitive data
|
|
7
|
+
*
|
|
8
|
+
* Priority order:
|
|
9
|
+
* 1. API keys and secrets (most specific, most sensitive)
|
|
10
|
+
* 2. Auth tokens and session IDs
|
|
11
|
+
* 3. PII (emails, phones, SSNs, credit cards)
|
|
12
|
+
* 4. Network identifiers (IPs, domains, URLs)
|
|
13
|
+
* 5. Internal identifiers (UUIDs, potentially-sensitive numbers)
|
|
14
|
+
*/
|
|
15
|
+
export const BUILTIN_PATTERNS = [
|
|
16
|
+
// ===== Priority 100: API Keys and Secrets =====
|
|
17
|
+
{
|
|
18
|
+
name: 'anthropic_api_key',
|
|
19
|
+
regex: /\b(sk-ant-[a-zA-Z0-9\-_]{20,})\b/g,
|
|
20
|
+
placeholder: (i) => `[ANTHROPIC_KEY_${i}]`,
|
|
21
|
+
priority: 100
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'openai_api_key',
|
|
25
|
+
regex: /\b(sk(-proj)?-[a-zA-Z0-9]{10,})\b/g,
|
|
26
|
+
placeholder: (i) => `[OPENAI_KEY_${i}]`,
|
|
27
|
+
priority: 100
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'stripe_live_key',
|
|
31
|
+
regex: /\b(sk_live_[a-zA-Z0-9]{24,})\b/g,
|
|
32
|
+
placeholder: (i) => `[STRIPE_LIVE_KEY_${i}]`,
|
|
33
|
+
priority: 100
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'stripe_test_key',
|
|
37
|
+
regex: /\b(sk_test_[a-zA-Z0-9]{24,})\b/g,
|
|
38
|
+
placeholder: (i) => `[STRIPE_TEST_KEY_${i}]`,
|
|
39
|
+
priority: 100
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'aws_access_key',
|
|
43
|
+
regex: /\b(AKIA[0-9A-Z]{16})\b/g,
|
|
44
|
+
placeholder: (i) => `[AWS_ACCESS_KEY_${i}]`,
|
|
45
|
+
priority: 100
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'github_token',
|
|
49
|
+
regex: /\b(ghp_|gho_|ghu_|ghs_|ghr_)[a-zA-Z0-9]{36,}\b/g,
|
|
50
|
+
placeholder: (i) => `[GITHUB_TOKEN_${i}]`,
|
|
51
|
+
priority: 100
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'jwt_token',
|
|
55
|
+
regex: /\b(eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+)\b/g,
|
|
56
|
+
placeholder: (i) => `[JWT_${i}]`,
|
|
57
|
+
priority: 100
|
|
58
|
+
},
|
|
59
|
+
// Generic API key patterns (must come after specific ones)
|
|
60
|
+
{
|
|
61
|
+
name: 'api_key_equals',
|
|
62
|
+
regex: /(['"]?(api_key|apikey|api-key|x-api-key|authorization|bearer|token)['"]?\s*[:=]\s*['"]?)([a-zA-Z0-9\-_\.]{16,})(['"]?)/gi,
|
|
63
|
+
placeholder: (i) => `$1[API_KEY_${i}]$4`,
|
|
64
|
+
priority: 95
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'aws_secret',
|
|
68
|
+
regex: /(['"]?(aws_secret_access_key|secret_access_key|secret_key)['"]?\s*[:=]\s*['"]?)([a-zA-Z0-9/+=]{16,})(['"]?)/gi,
|
|
69
|
+
placeholder: (i) => `$1[AWS_SECRET_${i}]$4`,
|
|
70
|
+
priority: 95
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'session_token',
|
|
74
|
+
regex: /(['"]?(session|session_id|sessionid|sess)['"]?\s*[:=]\s*['"]?)([a-zA-Z0-9\-_]{16,})(['"]?)/gi,
|
|
75
|
+
placeholder: (i) => `$1[SESSION_${i}]$4`,
|
|
76
|
+
priority: 90
|
|
77
|
+
},
|
|
78
|
+
// ===== Priority 80: PII =====
|
|
79
|
+
{
|
|
80
|
+
name: 'email',
|
|
81
|
+
regex: /\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\b/g,
|
|
82
|
+
placeholder: (i) => `[EMAIL_${i}]`,
|
|
83
|
+
priority: 80
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'ssn',
|
|
87
|
+
regex: /\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g,
|
|
88
|
+
placeholder: (i) => `[SSN_${i}]`,
|
|
89
|
+
priority: 80
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'credit_card',
|
|
93
|
+
regex: /\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g,
|
|
94
|
+
placeholder: (i) => `[CARD_${i}]`,
|
|
95
|
+
priority: 80
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: 'phone_us',
|
|
99
|
+
regex: /\b(\+?1[-.\s]?)?\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}\b/g,
|
|
100
|
+
placeholder: (i) => `[PHONE_${i}]`,
|
|
101
|
+
priority: 80
|
|
102
|
+
},
|
|
103
|
+
// ===== Priority 60: URLs =====
|
|
104
|
+
{
|
|
105
|
+
name: 'url_with_creds',
|
|
106
|
+
regex: /\b([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)([^:/\s]+):([^\s@/]+)@/g,
|
|
107
|
+
placeholder: (i) => `$1[CREDENTIALS_${i}]@`,
|
|
108
|
+
priority: 60
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'url_internal',
|
|
112
|
+
regex: /\bhttps?:\/\/(?:[a-zA-Z0-9-]+\.)?(?:internal|private|localhost|127\.0\.0\.1|10\.|192\.168\.|172\.1[6-9]\.|172\.2[0-9]\.|172\.3[01]\.)[^\s]*\b/gi,
|
|
113
|
+
placeholder: (i) => `[INTERNAL_URL_${i}]`,
|
|
114
|
+
priority: 55
|
|
115
|
+
},
|
|
116
|
+
// ===== Priority 40: Network =====
|
|
117
|
+
{
|
|
118
|
+
name: 'ip_address',
|
|
119
|
+
regex: /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/g,
|
|
120
|
+
placeholder: (i) => `[IP_${i}]`,
|
|
121
|
+
priority: 40
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'ipv6',
|
|
125
|
+
regex: /\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,
|
|
126
|
+
placeholder: (i) => `[IPV6_${i}]`,
|
|
127
|
+
priority: 40
|
|
128
|
+
},
|
|
129
|
+
// ===== Priority 30: Identifiers =====
|
|
130
|
+
{
|
|
131
|
+
name: 'uuid',
|
|
132
|
+
regex: /\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/g,
|
|
133
|
+
placeholder: (i) => `[UUID_${i}]`,
|
|
134
|
+
priority: 30
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'hash_sha256',
|
|
138
|
+
regex: /\b[a-f0-9]{64}\b/g,
|
|
139
|
+
placeholder: (i) => `[SHA256_${i}]`,
|
|
140
|
+
priority: 25
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'hash_md5',
|
|
144
|
+
regex: /\b[a-f0-9]{32}\b/g,
|
|
145
|
+
placeholder: (i) => `[MD5_${i}]`,
|
|
146
|
+
priority: 25
|
|
147
|
+
},
|
|
148
|
+
// ===== Priority 20: File Paths =====
|
|
149
|
+
{
|
|
150
|
+
name: 'file_path_unix',
|
|
151
|
+
regex: /\/(?:home|Users|var|etc|opt|usr|root|tmp)\/[^\s<>"{}|\\^`\[\]]*/g,
|
|
152
|
+
placeholder: (i) => `[PATH_${i}]`,
|
|
153
|
+
priority: 20
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'file_path_windows',
|
|
157
|
+
regex: /(?:[A-Z]:\\(?:Users|Program Files|Windows|ProgramData|temp)[^\s<>"{}|\\^`\[\]]*)|(?:\\\\[^\s<>"{}|\\^`\[\]]+)/g,
|
|
158
|
+
placeholder: (i) => `[PATH_${i}]`,
|
|
159
|
+
priority: 20
|
|
160
|
+
}
|
|
161
|
+
];
|
|
162
|
+
/**
|
|
163
|
+
* Get patterns by mask level
|
|
164
|
+
*/
|
|
165
|
+
export function getPatternsByLevel(level) {
|
|
166
|
+
const priority = (p) => p.priority ?? 50;
|
|
167
|
+
switch (level) {
|
|
168
|
+
case 'basic':
|
|
169
|
+
return BUILTIN_PATTERNS.filter(p => priority(p) >= 90);
|
|
170
|
+
case 'standard':
|
|
171
|
+
return BUILTIN_PATTERNS.filter(p => priority(p) >= 40);
|
|
172
|
+
case 'aggressive':
|
|
173
|
+
return BUILTIN_PATTERNS;
|
|
174
|
+
default:
|
|
175
|
+
return BUILTIN_PATTERNS.filter(p => priority(p) >= 40);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get pattern by name
|
|
180
|
+
*/
|
|
181
|
+
export function getPatternByName(name) {
|
|
182
|
+
return BUILTIN_PATTERNS.find(p => p.name === name);
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../src/patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scanner - scan codebases for sensitive data
|
|
3
|
+
*
|
|
4
|
+
* Recursively scans directories, finds files, checks for patterns
|
|
5
|
+
*/
|
|
6
|
+
export interface ScanResult {
|
|
7
|
+
file: string;
|
|
8
|
+
line: number;
|
|
9
|
+
pattern: string;
|
|
10
|
+
placeholder: string;
|
|
11
|
+
lineContent: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ScanReport {
|
|
14
|
+
scans: {
|
|
15
|
+
totalFiles: number;
|
|
16
|
+
scannedFiles: number;
|
|
17
|
+
skippedFiles: number;
|
|
18
|
+
};
|
|
19
|
+
findings: ScanResult[];
|
|
20
|
+
summary: {
|
|
21
|
+
byPattern: Record<string, number>;
|
|
22
|
+
byFile: Record<string, number>;
|
|
23
|
+
total: number;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface ScanOptions {
|
|
27
|
+
/** File extensions to scan (empty = all) */
|
|
28
|
+
extensions?: string[];
|
|
29
|
+
/** Patterns to exclude (regex) */
|
|
30
|
+
excludePatterns?: RegExp[];
|
|
31
|
+
/** Directories to skip */
|
|
32
|
+
skipDirs?: string[];
|
|
33
|
+
/** Max file size in bytes */
|
|
34
|
+
maxSize?: number;
|
|
35
|
+
/** Fail on detection (for CI/CD) */
|
|
36
|
+
failOnDetect?: boolean;
|
|
37
|
+
/** Masking level */
|
|
38
|
+
level?: 'basic' | 'standard' | 'aggressive';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Scanner - find secrets in codebases
|
|
42
|
+
*/
|
|
43
|
+
export declare class Scanner {
|
|
44
|
+
private masker;
|
|
45
|
+
private options;
|
|
46
|
+
constructor(options?: ScanOptions);
|
|
47
|
+
/**
|
|
48
|
+
* Scan a directory recursively
|
|
49
|
+
*/
|
|
50
|
+
scan(dir: string): Promise<ScanReport>;
|
|
51
|
+
/**
|
|
52
|
+
* Scan a single file
|
|
53
|
+
*/
|
|
54
|
+
scanFile(filePath: string): ScanResult[];
|
|
55
|
+
/**
|
|
56
|
+
* Format report as text
|
|
57
|
+
*/
|
|
58
|
+
formatReport(report: ScanReport, baseDir: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Get severity icon for pattern
|
|
61
|
+
*/
|
|
62
|
+
private getSeverityIcon;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Error thrown when sensitive patterns are detected
|
|
66
|
+
*/
|
|
67
|
+
export declare class ScanError extends Error {
|
|
68
|
+
report: ScanReport;
|
|
69
|
+
constructor(message: string, report: ScanReport);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Convenience function to scan a directory
|
|
73
|
+
*/
|
|
74
|
+
export declare function scanDirectory(dir: string, options?: ScanOptions): Promise<ScanReport>;
|
|
75
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE;QACL,UAAU,EAAE,MAAM,CAAA;QAClB,YAAY,EAAE,MAAM,CAAA;QACpB,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,QAAQ,EAAE,UAAU,EAAE,CAAA;IACtB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC9B,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,kCAAkC;IAClC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oCAAoC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,oBAAoB;IACpB,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,YAAY,CAAA;CAC5C;AA4BD;;GAEG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAuB;gBAE1B,OAAO,GAAE,WAAgB;IAYrC;;OAEG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAmG5C;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE;IAkCxC;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAiDzD;;OAEG;IACH,OAAO,CAAC,eAAe;CAkBxB;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAC3B,MAAM,EAAE,UAAU,CAAA;gBAEb,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU;CAKhD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,CAAC,CAGrB"}
|
package/dist/scanner.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scanner - scan codebases for sensitive data
|
|
3
|
+
*
|
|
4
|
+
* Recursively scans directories, finds files, checks for patterns
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
7
|
+
import { join, extname, relative, resolve } from 'path';
|
|
8
|
+
import { DataMasker } from './masker.js';
|
|
9
|
+
const DEFAULT_SKIP_DIRS = [
|
|
10
|
+
'node_modules',
|
|
11
|
+
'.git',
|
|
12
|
+
'dist',
|
|
13
|
+
'build',
|
|
14
|
+
'target',
|
|
15
|
+
'vendor',
|
|
16
|
+
'.venv',
|
|
17
|
+
'venv',
|
|
18
|
+
'__pycache__',
|
|
19
|
+
'.next',
|
|
20
|
+
'.nuxt',
|
|
21
|
+
'coverage'
|
|
22
|
+
];
|
|
23
|
+
const TEXT_EXTENSIONS = [
|
|
24
|
+
'.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs',
|
|
25
|
+
'.py', '.rb', '.go', '.rs', '.java', '.kt', '.swift',
|
|
26
|
+
'.sh', '.bash', '.zsh', '.fish',
|
|
27
|
+
'.env', '.config', '.conf', '.ini', '.yaml', '.yml', '.json', '.toml',
|
|
28
|
+
'.md', '.txt', '.csv', '.log',
|
|
29
|
+
'.sql', '.graphql', '.gql',
|
|
30
|
+
'.html', '.css', '.scss', '.less',
|
|
31
|
+
'.xml', '.dto'
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Scanner - find secrets in codebases
|
|
35
|
+
*/
|
|
36
|
+
export class Scanner {
|
|
37
|
+
masker;
|
|
38
|
+
options;
|
|
39
|
+
constructor(options = {}) {
|
|
40
|
+
this.masker = new DataMasker();
|
|
41
|
+
this.options = {
|
|
42
|
+
extensions: options.extensions || TEXT_EXTENSIONS,
|
|
43
|
+
excludePatterns: options.excludePatterns || [],
|
|
44
|
+
skipDirs: [...DEFAULT_SKIP_DIRS, ...(options.skipDirs || [])],
|
|
45
|
+
maxSize: options.maxSize || 1024 * 1024, // 1MB default
|
|
46
|
+
failOnDetect: options.failOnDetect || false,
|
|
47
|
+
level: options.level || 'standard'
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Scan a directory recursively
|
|
52
|
+
*/
|
|
53
|
+
async scan(dir) {
|
|
54
|
+
const findings = [];
|
|
55
|
+
let totalFiles = 0;
|
|
56
|
+
let scannedFiles = 0;
|
|
57
|
+
let skippedFiles = 0;
|
|
58
|
+
const walkDir = (currentDir) => {
|
|
59
|
+
try {
|
|
60
|
+
const entries = readdirSync(currentDir);
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
const fullPath = join(currentDir, entry);
|
|
63
|
+
const stat = statSync(fullPath);
|
|
64
|
+
// Skip directories in skip list
|
|
65
|
+
if (stat.isDirectory()) {
|
|
66
|
+
if (this.options.skipDirs.includes(entry)) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
walkDir(fullPath);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
// Only scan files
|
|
73
|
+
if (!stat.isFile()) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
totalFiles++;
|
|
77
|
+
// Check file extension
|
|
78
|
+
const ext = extname(entry);
|
|
79
|
+
if (this.options.extensions.length > 0 &&
|
|
80
|
+
!this.options.extensions.includes(ext)) {
|
|
81
|
+
skippedFiles++;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
// Check file size
|
|
85
|
+
if (stat.size > this.options.maxSize) {
|
|
86
|
+
skippedFiles++;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// Check exclude patterns
|
|
90
|
+
const relPath = relative(dir, fullPath);
|
|
91
|
+
if (this.options.excludePatterns.some(pattern => pattern.test(relPath))) {
|
|
92
|
+
skippedFiles++;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
// Scan the file
|
|
96
|
+
const fileFindings = this.scanFile(fullPath);
|
|
97
|
+
findings.push(...fileFindings);
|
|
98
|
+
scannedFiles++;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
// Skip files we can't read (permissions, etc.)
|
|
103
|
+
skippedFiles++;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
walkDir(resolve(dir));
|
|
107
|
+
// Generate summary
|
|
108
|
+
const byPattern = {};
|
|
109
|
+
const byFile = {};
|
|
110
|
+
for (const finding of findings) {
|
|
111
|
+
byPattern[finding.pattern] = (byPattern[finding.pattern] || 0) + 1;
|
|
112
|
+
const relPath = relative(dir, finding.file);
|
|
113
|
+
byFile[relPath] = (byFile[relPath] || 0) + 1;
|
|
114
|
+
}
|
|
115
|
+
const report = {
|
|
116
|
+
scans: {
|
|
117
|
+
totalFiles,
|
|
118
|
+
scannedFiles,
|
|
119
|
+
skippedFiles
|
|
120
|
+
},
|
|
121
|
+
findings,
|
|
122
|
+
summary: {
|
|
123
|
+
byPattern,
|
|
124
|
+
byFile,
|
|
125
|
+
total: findings.length
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
// Fail if requested and findings exist
|
|
129
|
+
if (this.options.failOnDetect && findings.length > 0) {
|
|
130
|
+
throw new ScanError(`Found ${findings.length} sensitive pattern(s) in codebase`, report);
|
|
131
|
+
}
|
|
132
|
+
return report;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Scan a single file
|
|
136
|
+
*/
|
|
137
|
+
scanFile(filePath) {
|
|
138
|
+
const findings = [];
|
|
139
|
+
try {
|
|
140
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
141
|
+
const lines = content.split('\n');
|
|
142
|
+
for (let i = 0; i < lines.length; i++) {
|
|
143
|
+
const line = lines[i];
|
|
144
|
+
const result = this.masker.mask(line, { level: this.options.level });
|
|
145
|
+
// Check if anything was masked
|
|
146
|
+
if (result.stats.total > 0) {
|
|
147
|
+
// Find which patterns matched
|
|
148
|
+
for (const [pattern, count] of Object.entries(result.stats.byPattern)) {
|
|
149
|
+
for (let j = 0; j < count; j++) {
|
|
150
|
+
findings.push({
|
|
151
|
+
file: filePath,
|
|
152
|
+
line: i + 1,
|
|
153
|
+
pattern,
|
|
154
|
+
placeholder: `[${pattern.toUpperCase()}_${j + 1}]`,
|
|
155
|
+
lineContent: line.trim()
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
// Skip files that can't be read as text
|
|
164
|
+
}
|
|
165
|
+
return findings;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Format report as text
|
|
169
|
+
*/
|
|
170
|
+
formatReport(report, baseDir) {
|
|
171
|
+
const lines = [];
|
|
172
|
+
lines.push('🔍 llm-mask Scan Report');
|
|
173
|
+
lines.push('');
|
|
174
|
+
lines.push(`Scanned: ${report.scans.scannedFiles} files`);
|
|
175
|
+
lines.push(`Skipped: ${report.scans.skippedFiles} files`);
|
|
176
|
+
lines.push(`Findings: ${report.summary.total} sensitive pattern(s)`);
|
|
177
|
+
lines.push('');
|
|
178
|
+
if (report.findings.length === 0) {
|
|
179
|
+
lines.push('✅ No sensitive patterns detected!');
|
|
180
|
+
return lines.join('\n');
|
|
181
|
+
}
|
|
182
|
+
lines.push('⚠️ Findings:');
|
|
183
|
+
lines.push('');
|
|
184
|
+
// Group by file
|
|
185
|
+
const byFile = {};
|
|
186
|
+
for (const finding of report.findings) {
|
|
187
|
+
const relPath = relative(baseDir, finding.file);
|
|
188
|
+
if (!byFile[relPath]) {
|
|
189
|
+
byFile[relPath] = [];
|
|
190
|
+
}
|
|
191
|
+
byFile[relPath].push(finding);
|
|
192
|
+
}
|
|
193
|
+
for (const [file, fileFindings] of Object.entries(byFile)) {
|
|
194
|
+
lines.push(`${file}:`);
|
|
195
|
+
for (const finding of fileFindings) {
|
|
196
|
+
const icon = this.getSeverityIcon(finding.pattern);
|
|
197
|
+
lines.push(` ${icon} Line ${finding.line}: ${finding.pattern}`);
|
|
198
|
+
lines.push(` ${finding.lineContent.substring(0, 80)}${finding.lineContent.length > 80 ? '...' : ''}`);
|
|
199
|
+
}
|
|
200
|
+
lines.push('');
|
|
201
|
+
}
|
|
202
|
+
// Summary by pattern
|
|
203
|
+
lines.push('Summary by pattern:');
|
|
204
|
+
for (const [pattern, count] of Object.entries(report.summary.byPattern)) {
|
|
205
|
+
lines.push(` ${pattern}: ${count}`);
|
|
206
|
+
}
|
|
207
|
+
return lines.join('\n');
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get severity icon for pattern
|
|
211
|
+
*/
|
|
212
|
+
getSeverityIcon(pattern) {
|
|
213
|
+
const critical = [
|
|
214
|
+
'openai_api_key', 'anthropic_api_key', 'stripe_live_key',
|
|
215
|
+
'aws_access_key', 'aws_secret', 'github_token'
|
|
216
|
+
];
|
|
217
|
+
const warning = [
|
|
218
|
+
'email', 'ip_address', 'uuid', 'jwt_token', 'api_key_equals'
|
|
219
|
+
];
|
|
220
|
+
if (critical.some(p => pattern.includes(p))) {
|
|
221
|
+
return '❌';
|
|
222
|
+
}
|
|
223
|
+
if (warning.some(p => pattern.includes(p))) {
|
|
224
|
+
return '⚠️ ';
|
|
225
|
+
}
|
|
226
|
+
return '🔒';
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Error thrown when sensitive patterns are detected
|
|
231
|
+
*/
|
|
232
|
+
export class ScanError extends Error {
|
|
233
|
+
report;
|
|
234
|
+
constructor(message, report) {
|
|
235
|
+
super(message);
|
|
236
|
+
this.name = 'ScanError';
|
|
237
|
+
this.report = report;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Convenience function to scan a directory
|
|
242
|
+
*/
|
|
243
|
+
export async function scanDirectory(dir, options) {
|
|
244
|
+
const scanner = new Scanner(options);
|
|
245
|
+
return scanner.scan(dir);
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,sEAAsE;AACtE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reversible tokenization with deterministic encryption
|
|
3
|
+
*
|
|
4
|
+
* Uses HMAC-based deterministic encryption to ensure:
|
|
5
|
+
* - Same input always produces same token (consistency)
|
|
6
|
+
* - Token cannot be reversed without the salt
|
|
7
|
+
* - Works across different processes/machines with same salt
|
|
8
|
+
*/
|
|
9
|
+
export interface TokenizerConfig {
|
|
10
|
+
/** Salt for HMAC (generate one and store it securely) */
|
|
11
|
+
salt: string;
|
|
12
|
+
/** Token prefix */
|
|
13
|
+
prefix?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Tokenizer - reversible masking with deterministic encryption
|
|
17
|
+
*/
|
|
18
|
+
export declare class Tokenizer {
|
|
19
|
+
private salt;
|
|
20
|
+
private prefix;
|
|
21
|
+
constructor(config: TokenizerConfig);
|
|
22
|
+
/**
|
|
23
|
+
* Tokenize a value
|
|
24
|
+
*
|
|
25
|
+
* @param value - The sensitive value to tokenize
|
|
26
|
+
* @param context - Optional context for namespacing (e.g., "email", "api_key")
|
|
27
|
+
* @returns Token that can be safely shared
|
|
28
|
+
*/
|
|
29
|
+
tokenize(value: string, context?: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Check if a value is a token from this tokenizer
|
|
32
|
+
*/
|
|
33
|
+
isToken(value: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Extract context from token if present
|
|
36
|
+
*/
|
|
37
|
+
getTokenContext(token: string): string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Verify a token matches an original value
|
|
40
|
+
*
|
|
41
|
+
* Useful for validation without storing mappings
|
|
42
|
+
*/
|
|
43
|
+
verify(token: string, original: string): boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Generate a random salt for tokenizer
|
|
47
|
+
*
|
|
48
|
+
* Save this securely - you'll need it to detokenize
|
|
49
|
+
*/
|
|
50
|
+
export declare function generateSalt(): string;
|
|
51
|
+
/**
|
|
52
|
+
* Default tokenizer instance (uses a default salt - NOT SECURE for production)
|
|
53
|
+
*
|
|
54
|
+
* For production, create your own instance with a secure salt
|
|
55
|
+
*/
|
|
56
|
+
export declare const defaultTokenizer: Tokenizer;
|
|
57
|
+
/**
|
|
58
|
+
* Convenience functions
|
|
59
|
+
*/
|
|
60
|
+
export declare function tokenize(value: string, context?: string): string;
|
|
61
|
+
export declare function isToken(value: string): boolean;
|
|
62
|
+
//# sourceMappingURL=tokenizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../src/tokenizer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,MAAM,CAAQ;gBAEV,MAAM,EAAE,eAAe;IAKnC;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;IAiBjD;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAI/B;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAa7C;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;CAKjD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,WAG3B,CAAA;AAEF;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE9C"}
|