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.
Files changed (88) hide show
  1. package/.github/workflows/llm-mask-check.yml +62 -0
  2. package/LICENSE +21 -0
  3. package/README.md +549 -0
  4. package/dist/audit.d.ts +56 -0
  5. package/dist/audit.d.ts.map +1 -0
  6. package/dist/audit.js +90 -0
  7. package/dist/audit.js.map +1 -0
  8. package/dist/cli-old.d.ts +12 -0
  9. package/dist/cli-old.d.ts.map +1 -0
  10. package/dist/cli-old.js +257 -0
  11. package/dist/cli-old.js.map +1 -0
  12. package/dist/cli.d.ts +19 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +197 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/commands.d.ts +9 -0
  17. package/dist/commands.d.ts.map +1 -0
  18. package/dist/commands.js +121 -0
  19. package/dist/commands.js.map +1 -0
  20. package/dist/config.d.ts +38 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/config.js +81 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/context-detection.d.ts +54 -0
  25. package/dist/context-detection.d.ts.map +1 -0
  26. package/dist/context-detection.js +219 -0
  27. package/dist/context-detection.js.map +1 -0
  28. package/dist/diff-masking.d.ts +51 -0
  29. package/dist/diff-masking.d.ts.map +1 -0
  30. package/dist/diff-masking.js +121 -0
  31. package/dist/diff-masking.js.map +1 -0
  32. package/dist/executor.d.ts +105 -0
  33. package/dist/executor.d.ts.map +1 -0
  34. package/dist/executor.js +250 -0
  35. package/dist/executor.js.map +1 -0
  36. package/dist/executor.test.d.ts +5 -0
  37. package/dist/executor.test.d.ts.map +1 -0
  38. package/dist/executor.test.js +500 -0
  39. package/dist/executor.test.js.map +1 -0
  40. package/dist/features.test.d.ts +5 -0
  41. package/dist/features.test.d.ts.map +1 -0
  42. package/dist/features.test.js +118 -0
  43. package/dist/features.test.js.map +1 -0
  44. package/dist/formatter.d.ts +54 -0
  45. package/dist/formatter.d.ts.map +1 -0
  46. package/dist/formatter.js +139 -0
  47. package/dist/formatter.js.map +1 -0
  48. package/dist/index.d.ts +36 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +37 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/language-patterns.d.ts +39 -0
  53. package/dist/language-patterns.d.ts.map +1 -0
  54. package/dist/language-patterns.js +177 -0
  55. package/dist/language-patterns.js.map +1 -0
  56. package/dist/masker.d.ts +100 -0
  57. package/dist/masker.d.ts.map +1 -0
  58. package/dist/masker.js +255 -0
  59. package/dist/masker.js.map +1 -0
  60. package/dist/masker.test.d.ts +11 -0
  61. package/dist/masker.test.d.ts.map +1 -0
  62. package/dist/masker.test.js +162 -0
  63. package/dist/masker.test.js.map +1 -0
  64. package/dist/mcp-server.d.ts +9 -0
  65. package/dist/mcp-server.d.ts.map +1 -0
  66. package/dist/mcp-server.js +494 -0
  67. package/dist/mcp-server.js.map +1 -0
  68. package/dist/patterns.d.ts +25 -0
  69. package/dist/patterns.d.ts.map +1 -0
  70. package/dist/patterns.js +184 -0
  71. package/dist/patterns.js.map +1 -0
  72. package/dist/scanner.d.ts +75 -0
  73. package/dist/scanner.d.ts.map +1 -0
  74. package/dist/scanner.js +247 -0
  75. package/dist/scanner.js.map +1 -0
  76. package/dist/test-utils.d.ts +5 -0
  77. package/dist/test-utils.d.ts.map +1 -0
  78. package/dist/test-utils.js +6 -0
  79. package/dist/test-utils.js.map +1 -0
  80. package/dist/tokenizer.d.ts +62 -0
  81. package/dist/tokenizer.d.ts.map +1 -0
  82. package/dist/tokenizer.js +95 -0
  83. package/dist/tokenizer.js.map +1 -0
  84. package/dist/types.d.ts +63 -0
  85. package/dist/types.d.ts.map +1 -0
  86. package/dist/types.js +16 -0
  87. package/dist/types.js.map +1 -0
  88. package/package.json +60 -0
@@ -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"}
@@ -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,5 @@
1
+ /**
2
+ * Test utilities - compatibility layer for bun test
3
+ */
4
+ export { describe, it, expect, test } from 'bun:test';
5
+ //# sourceMappingURL=test-utils.d.ts.map
@@ -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,6 @@
1
+ /**
2
+ * Test utilities - compatibility layer for bun test
3
+ */
4
+ // Use built-in test from bun (available globally in test environment)
5
+ export { describe, it, expect, test } from 'bun:test';
6
+ //# sourceMappingURL=test-utils.js.map
@@ -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"}