guardrail-security 1.0.2 → 2.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 (60) hide show
  1. package/dist/sbom/generator.d.ts +42 -0
  2. package/dist/sbom/generator.d.ts.map +1 -1
  3. package/dist/sbom/generator.js +168 -7
  4. package/dist/secrets/allowlist.d.ts +38 -0
  5. package/dist/secrets/allowlist.d.ts.map +1 -0
  6. package/dist/secrets/allowlist.js +131 -0
  7. package/dist/secrets/config-loader.d.ts +25 -0
  8. package/dist/secrets/config-loader.d.ts.map +1 -0
  9. package/dist/secrets/config-loader.js +103 -0
  10. package/dist/secrets/contextual-risk.d.ts +19 -0
  11. package/dist/secrets/contextual-risk.d.ts.map +1 -0
  12. package/dist/secrets/contextual-risk.js +88 -0
  13. package/dist/secrets/git-scanner.d.ts +29 -0
  14. package/dist/secrets/git-scanner.d.ts.map +1 -0
  15. package/dist/secrets/git-scanner.js +109 -0
  16. package/dist/secrets/guardian.d.ts +70 -57
  17. package/dist/secrets/guardian.d.ts.map +1 -1
  18. package/dist/secrets/guardian.js +531 -258
  19. package/dist/secrets/index.d.ts +4 -0
  20. package/dist/secrets/index.d.ts.map +1 -1
  21. package/dist/secrets/index.js +11 -1
  22. package/dist/secrets/patterns.d.ts +39 -10
  23. package/dist/secrets/patterns.d.ts.map +1 -1
  24. package/dist/secrets/patterns.js +129 -71
  25. package/dist/secrets/pre-commit.d.ts.map +1 -1
  26. package/dist/secrets/pre-commit.js +1 -1
  27. package/dist/secrets/vault-integration.d.ts.map +1 -1
  28. package/dist/secrets/vault-integration.js +1 -0
  29. package/dist/supply-chain/vulnerability-db.d.ts +89 -16
  30. package/dist/supply-chain/vulnerability-db.d.ts.map +1 -1
  31. package/dist/supply-chain/vulnerability-db.js +404 -115
  32. package/dist/utils/semver.d.ts +37 -0
  33. package/dist/utils/semver.d.ts.map +1 -0
  34. package/dist/utils/semver.js +109 -0
  35. package/package.json +17 -3
  36. package/src/__tests__/license/engine.test.ts +0 -250
  37. package/src/__tests__/supply-chain/typosquat.test.ts +0 -191
  38. package/src/attack-surface/analyzer.ts +0 -153
  39. package/src/attack-surface/index.ts +0 -5
  40. package/src/index.ts +0 -21
  41. package/src/languages/index.ts +0 -91
  42. package/src/languages/java-analyzer.ts +0 -490
  43. package/src/languages/python-analyzer.ts +0 -498
  44. package/src/license/compatibility-matrix.ts +0 -366
  45. package/src/license/engine.ts +0 -346
  46. package/src/license/index.ts +0 -6
  47. package/src/sbom/generator.ts +0 -355
  48. package/src/sbom/index.ts +0 -5
  49. package/src/secrets/guardian.ts +0 -468
  50. package/src/secrets/index.ts +0 -10
  51. package/src/secrets/patterns.ts +0 -186
  52. package/src/secrets/pre-commit.ts +0 -158
  53. package/src/secrets/vault-integration.ts +0 -360
  54. package/src/secrets/vault-providers.ts +0 -446
  55. package/src/supply-chain/detector.ts +0 -253
  56. package/src/supply-chain/index.ts +0 -11
  57. package/src/supply-chain/malicious-db.ts +0 -103
  58. package/src/supply-chain/script-analyzer.ts +0 -194
  59. package/src/supply-chain/typosquat.ts +0 -302
  60. package/src/supply-chain/vulnerability-db.ts +0 -386
@@ -1,468 +0,0 @@
1
- // Stub prisma for standalone use
2
- const prisma: any = null;
3
-
4
- // Local implementations of core utilities
5
- function calculateEntropy(str: string): number {
6
- const len = str.length;
7
- const charCounts: Record<string, number> = {};
8
- for (const char of str) {
9
- charCounts[char] = (charCounts[char] || 0) + 1;
10
- }
11
- let entropy = 0;
12
- for (const count of Object.values(charCounts)) {
13
- const p = count / len;
14
- entropy -= p * Math.log2(p);
15
- }
16
- return entropy;
17
- }
18
-
19
- function maskSensitiveValue(value: string): string {
20
- if (value.length <= 8) return '***';
21
- return value.slice(0, 4) + '...' + value.slice(-4);
22
- }
23
- import { SECRET_PATTERNS, TEST_PATTERNS, FALSE_POSITIVE_VALUES, SecretPattern } from './patterns';
24
- import { readFileSync } from 'fs';
25
- import { glob } from 'glob';
26
- import { join } from 'path';
27
-
28
- // Define SecretType locally since it's not exported from database
29
- export enum SecretType {
30
- API_KEY = 'api_key',
31
- PASSWORD = 'password',
32
- TOKEN = 'token',
33
- CERTIFICATE = 'certificate',
34
- PRIVATE_KEY = 'private_key',
35
- DATABASE_URL = 'database_url',
36
- JWT_SECRET = 'jwt_secret',
37
- AWS_ACCESS_KEY = 'aws_access_key',
38
- OTHER = 'other',
39
- AWS_SECRET_KEY = 'aws_secret_key',
40
- GITHUB_TOKEN = 'github_token',
41
- GOOGLE_API_KEY = 'google_api_key',
42
- STRIPE_KEY = 'stripe_key',
43
- JWT_TOKEN = 'jwt_token',
44
- SLACK_TOKEN = 'slack_token',
45
- API_KEY_GENERIC = 'api_key_generic',
46
- PASSWORD_GENERIC = 'password_generic'
47
- }
48
-
49
- /**
50
- * Secret detection result
51
- */
52
- export interface SecretDetection {
53
- id?: string;
54
- filePath: string;
55
- secretType: SecretType;
56
- maskedValue: string;
57
- location: {
58
- line: number;
59
- column: number;
60
- snippet: string;
61
- };
62
- confidence: number;
63
- entropy: number;
64
- isTest: boolean;
65
- isRevoked: boolean;
66
- recommendation: {
67
- action: 'remove' | 'move_to_env' | 'use_vault' | 'revoke_and_rotate';
68
- reason: string;
69
- remediation: string;
70
- };
71
- }
72
-
73
- /**
74
- * Scan options
75
- */
76
- export interface ScanOptions {
77
- excludeTests?: boolean;
78
- minConfidence?: number;
79
- excludePatterns?: string[];
80
- }
81
-
82
- /**
83
- * Project scan report
84
- */
85
- export interface ProjectScanReport {
86
- projectId: string;
87
- totalFiles: number;
88
- scannedFiles: number;
89
- detections: SecretDetection[];
90
- summary: {
91
- totalSecrets: number;
92
- byType: Record<string, number>;
93
- byRisk: { high: number; medium: number; low: number };
94
- };
95
- }
96
-
97
- /**
98
- * Secrets & Credential Guardian
99
- *
100
- * Detects exposed secrets and credentials in code
101
- */
102
- export class SecretsGuardian {
103
- /**
104
- * Scan content for secrets
105
- */
106
- async scanContent(
107
- content: string,
108
- filePath: string,
109
- options: ScanOptions = {}
110
- ): Promise<SecretDetection[]> {
111
- const detections: SecretDetection[] = [];
112
- const lines = content.split('\n');
113
-
114
- for (const pattern of SECRET_PATTERNS) {
115
- const matches = [...content.matchAll(new RegExp(pattern.pattern, 'g'))];
116
-
117
- for (const match of matches) {
118
- if (!match.index) continue;
119
-
120
- // Extract the secret value (first capturing group)
121
- const value = match[1] || match[0];
122
-
123
- // Calculate entropy
124
- const entropy = this.calculateEntropy(value);
125
-
126
- // Check minimum entropy requirement
127
- if (pattern.minEntropy && entropy < pattern.minEntropy) {
128
- continue;
129
- }
130
-
131
- // Find line number and column
132
- const beforeMatch = content.substring(0, match.index);
133
- const lineNumber = beforeMatch.split('\n').length;
134
- const lineStart = beforeMatch.lastIndexOf('\n') + 1;
135
- const column = match.index - lineStart + 1;
136
-
137
- // Get context
138
- const snippet = lines[lineNumber - 1] || '';
139
-
140
- // Check if it's a test value
141
- const isTest = this.isTestValue(value, snippet);
142
-
143
- // Check for false positives
144
- const isFalsePositive = this.isFalsePositive(value, pattern.type, snippet);
145
-
146
- if (isFalsePositive) {
147
- continue;
148
- }
149
-
150
- // Calculate confidence
151
- const confidence = this.calculateConfidence(value, pattern, entropy, isTest);
152
-
153
- // Skip if below minimum confidence
154
- if (options.minConfidence && confidence < options.minConfidence) {
155
- continue;
156
- }
157
-
158
- // Skip if excluding tests
159
- if (options.excludeTests && isTest) {
160
- continue;
161
- }
162
-
163
- // Mask the value
164
- const maskedValue = this.maskValue(value);
165
-
166
- // Generate recommendation
167
- const recommendation = this.generateRecommendation(pattern.type, isTest);
168
-
169
- // Create detection object
170
- const detection: SecretDetection = {
171
- id: undefined, // Will be set when saved to database
172
- filePath,
173
- secretType: pattern.type,
174
- maskedValue,
175
- location: {
176
- line: lineNumber,
177
- column,
178
- snippet: snippet.trim(),
179
- },
180
- confidence,
181
- entropy,
182
- isTest,
183
- isRevoked: false,
184
- recommendation,
185
- };
186
-
187
- detections.push(detection);
188
- }
189
- }
190
-
191
- return detections;
192
- }
193
-
194
- /**
195
- * Scan entire project
196
- */
197
- async scanProject(
198
- projectPath: string,
199
- projectId: string,
200
- options: ScanOptions = {}
201
- ): Promise<ProjectScanReport> {
202
- const excludePatterns = [
203
- '**/node_modules/**',
204
- '**/dist/**',
205
- '**/build/**',
206
- '**/.git/**',
207
- '**/coverage/**',
208
- '**/*.min.js',
209
- ...(options.excludePatterns || []),
210
- ];
211
-
212
- // Find all files to scan
213
- const files = await glob('**/*', {
214
- cwd: projectPath,
215
- ignore: excludePatterns,
216
- nodir: true,
217
- });
218
-
219
- const allDetections: SecretDetection[] = [];
220
- let scannedFiles = 0;
221
-
222
- for (const file of files) {
223
- try {
224
- const fullPath = join(projectPath, file);
225
- const content = readFileSync(fullPath, 'utf-8');
226
-
227
- const detections = await this.scanContent(content, file, options);
228
-
229
- // Save to database
230
- for (const detection of detections) {
231
- try {
232
- // @ts-ignore - secretDetection may not exist in schema yet
233
- await prisma.secretDetection.create({
234
- data: {
235
- projectId: 'default',
236
- filePath: detection.filePath
237
- } as any
238
- });
239
- } catch (error) {
240
- // Table may not exist - continue
241
- }
242
- }
243
-
244
- allDetections.push(...detections);
245
- scannedFiles++;
246
- } catch (error) {
247
- // Skip files that can't be read
248
- continue;
249
- }
250
- }
251
-
252
- // Generate summary
253
- const byType: Record<string, number> = {};
254
- const byRisk = { high: 0, medium: 0, low: 0 };
255
-
256
- for (const detection of allDetections) {
257
- byType[detection.secretType] = (byType[detection.secretType] || 0) + 1;
258
-
259
- if (detection.confidence >= 0.8) {
260
- byRisk.high++;
261
- } else if (detection.confidence >= 0.5) {
262
- byRisk.medium++;
263
- } else {
264
- byRisk.low++;
265
- }
266
- }
267
-
268
- return {
269
- projectId,
270
- totalFiles: files.length,
271
- scannedFiles,
272
- detections: allDetections,
273
- summary: {
274
- totalSecrets: allDetections.length,
275
- byType,
276
- byRisk,
277
- },
278
- };
279
- }
280
-
281
- /**
282
- * Calculate entropy for randomness detection
283
- */
284
- private calculateEntropy(str: string): number {
285
- return calculateEntropy(str);
286
- }
287
-
288
- /**
289
- * Check if likely test/example value
290
- */
291
- private isTestValue(value: string, context: string): boolean {
292
- const lowerValue = value.toLowerCase();
293
- const lowerContext = context.toLowerCase();
294
-
295
- // Check value itself
296
- for (const pattern of TEST_PATTERNS) {
297
- if (pattern.test(lowerValue)) {
298
- return true;
299
- }
300
- }
301
-
302
- // Check context
303
- if (
304
- lowerContext.includes('test') ||
305
- lowerContext.includes('example') ||
306
- lowerContext.includes('demo') ||
307
- lowerContext.includes('fixture') ||
308
- lowerContext.includes('mock')
309
- ) {
310
- return true;
311
- }
312
-
313
- return false;
314
- }
315
-
316
- /**
317
- * Check for false positives
318
- */
319
- private isFalsePositive(value: string, type: SecretType, _context: string): boolean {
320
- const lowerValue = value.toLowerCase();
321
-
322
- // Check against known false positives
323
- if (FALSE_POSITIVE_VALUES.has(lowerValue)) {
324
- return true;
325
- }
326
-
327
- // Check for placeholder patterns
328
- if (/^(x+|0+|1+|a+)$/i.test(value)) {
329
- return true;
330
- }
331
-
332
- // Check for repeated characters (likely placeholder)
333
- if (/(.)\1{10,}/.test(value)) {
334
- return true;
335
- }
336
-
337
- // JWT-specific false positive checks
338
- if (type === SecretType.JWT_TOKEN) {
339
- // Very simple/short payload might be example
340
- try {
341
- const parts = value.split('.');
342
- if (parts.length === 3 && parts[1]) {
343
- const payload = Buffer.from(parts[1], 'base64').toString();
344
- if (payload.length < 20) {
345
- return true;
346
- }
347
- }
348
- } catch {
349
- // Invalid JWT, might be false positive
350
- return true;
351
- }
352
- }
353
-
354
- return false;
355
- }
356
-
357
- /**
358
- * Calculate confidence score
359
- */
360
- private calculateConfidence(
361
- value: string,
362
- pattern: SecretPattern,
363
- entropy: number,
364
- isTest: boolean
365
- ): number {
366
- let confidence = 0.7; // Base confidence
367
-
368
- // Increase confidence for high entropy
369
- if (entropy > 4.5) {
370
- confidence += 0.2;
371
- } else if (entropy > 4.0) {
372
- confidence += 0.1;
373
- }
374
-
375
- // Decrease confidence for test values
376
- if (isTest) {
377
- confidence -= 0.3;
378
- }
379
-
380
- // Pattern-specific adjustments
381
- if (pattern.type === SecretType.AWS_ACCESS_KEY && value.startsWith('AKIA')) {
382
- confidence += 0.1;
383
- }
384
-
385
- if (pattern.type === SecretType.GITHUB_TOKEN && /^gh[pos]_/.test(value)) {
386
- confidence += 0.1;
387
- }
388
-
389
- return Math.max(0, Math.min(1, confidence));
390
- }
391
-
392
- /**
393
- * Mask secret for safe logging
394
- */
395
- private maskValue(value: string): string {
396
- return maskSensitiveValue(value);
397
- }
398
-
399
- /**
400
- * Generate recommendation
401
- */
402
- private generateRecommendation(
403
- type: SecretType,
404
- isTest: boolean
405
- ): {
406
- action: 'remove' | 'move_to_env' | 'use_vault' | 'revoke_and_rotate';
407
- reason: string;
408
- remediation: string;
409
- } {
410
- if (isTest) {
411
- return {
412
- action: 'remove',
413
- reason: 'Test credential detected in code',
414
- remediation: 'Remove test credentials and use mocking instead',
415
- };
416
- }
417
-
418
- // High-risk secrets require rotation
419
- const highRiskTypes: SecretType[] = [
420
- 'AWS_SECRET_KEY' as SecretType,
421
- 'GITHUB_TOKEN' as SecretType,
422
- 'STRIPE_KEY' as SecretType,
423
- 'PRIVATE_KEY' as SecretType,
424
- ];
425
-
426
- if (highRiskTypes.includes(type)) {
427
- return {
428
- action: 'revoke_and_rotate',
429
- reason: 'High-risk credential exposed in code',
430
- remediation: 'Immediately revoke this credential and rotate to a new one. Store in secure vault or environment variables.',
431
- };
432
- }
433
-
434
- // Medium-risk can use env vars
435
- return {
436
- action: 'move_to_env',
437
- reason: 'Credential should not be hardcoded',
438
- remediation: 'Move to environment variables or secure vault (e.g., AWS Secrets Manager, HashiCorp Vault)',
439
- };
440
- }
441
-
442
- /**
443
- * Get project secrets report
444
- */
445
- async getProjectReport(projectId: string): Promise<SecretDetection[]> {
446
- // @ts-ignore - secretDetection may not exist in schema yet
447
- const detections = await prisma.secretDetection.findMany({
448
- where: { projectId },
449
- orderBy: { createdAt: 'desc' },
450
- });
451
-
452
- return detections.map((s: any) => ({
453
- id: s.id,
454
- filePath: s.filePath,
455
- secretType: s.secretType as SecretType,
456
- maskedValue: s.maskedValue,
457
- location: s.location as any,
458
- confidence: s.confidence,
459
- entropy: s.entropy,
460
- isTest: s.isTest,
461
- isRevoked: s.isRevoked,
462
- recommendation: s.recommendation as any,
463
- }));
464
- }
465
- }
466
-
467
- // Export singleton
468
- export const secretsGuardian = new SecretsGuardian();
@@ -1,10 +0,0 @@
1
- /**
2
- * Secrets & Credential Guardian
3
- *
4
- * Detects and prevents exposure of secrets and credentials
5
- */
6
-
7
- export * from './patterns';
8
- export { secretsGuardian, SecretsGuardian } from './guardian';
9
- export { preCommitHook } from './pre-commit';
10
- export { vaultIntegration } from './vault-integration';
@@ -1,186 +0,0 @@
1
- // Define SecretType locally since it's not exported from database
2
- export enum SecretType {
3
- API_KEY = 'api_key',
4
- PASSWORD = 'password',
5
- TOKEN = 'token',
6
- CERTIFICATE = 'certificate',
7
- PRIVATE_KEY = 'private_key',
8
- DATABASE_URL = 'database_url',
9
- JWT_SECRET = 'jwt_secret',
10
- AWS_ACCESS_KEY = 'aws_access_key',
11
- OTHER = 'other',
12
- AWS_SECRET_KEY = 'aws_secret_key',
13
- GITHUB_TOKEN = 'github_token',
14
- GOOGLE_API_KEY = 'google_api_key',
15
- STRIPE_KEY = 'stripe_key',
16
- JWT_TOKEN = 'jwt_token',
17
- SLACK_TOKEN = 'slack_token',
18
- API_KEY_GENERIC = 'api_key_generic',
19
- }
20
-
21
- /**
22
- * Secret detection pattern
23
- */
24
- export interface SecretPattern {
25
- type: SecretType;
26
- name: string;
27
- pattern: RegExp;
28
- minEntropy?: number;
29
- description: string;
30
- examples: string[];
31
- }
32
-
33
- /**
34
- * Comprehensive secret detection patterns
35
- */
36
- export const SECRET_PATTERNS: SecretPattern[] = [
37
- // AWS Access Keys
38
- {
39
- type: 'AWS_ACCESS_KEY' as SecretType,
40
- name: 'AWS Access Key ID',
41
- pattern: /(AKIA[0-9A-Z]{16})/,
42
- minEntropy: 3.5,
43
- description: 'AWS Access Key ID (starts with AKIA)',
44
- examples: ['AKIAIOSFODNN7EXAMPLE'],
45
- },
46
-
47
- // AWS Secret Keys
48
- {
49
- type: 'AWS_SECRET_KEY' as SecretType,
50
- name: 'AWS Secret Access Key',
51
- pattern: /aws[_\s]*secret[_\s]*access[_\s]*key[_\s]*[=:]\s*['"]?([A-Za-z0-9/+=]{40})['"]?/i,
52
- minEntropy: 4.5,
53
- description: 'AWS Secret Access Key (40 characters)',
54
- examples: ['aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'],
55
- },
56
-
57
- // GitHub Personal Access Tokens
58
- {
59
- type: 'GITHUB_TOKEN' as SecretType,
60
- name: 'GitHub Personal Access Token',
61
- pattern: /(ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|ghu_[a-zA-Z0-9]{36}|ghs_[a-zA-Z0-9]{36}|ghr_[a-zA-Z0-9]{36})/,
62
- description: 'GitHub Personal Access Token (ghp_, gho_, ghu_, ghs_, ghr_)',
63
- examples: ['ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'],
64
- },
65
-
66
- // Google API Keys
67
- {
68
- type: 'GOOGLE_API_KEY' as SecretType,
69
- name: 'Google API Key',
70
- pattern: /(AIza[0-9A-Za-z\-_]{35})/,
71
- description: 'Google API Key (starts with AIza)',
72
- examples: ['AIzaSyDaGmWKa4JsXZ-HjGw7ISLn_3namBGewQe'],
73
- },
74
-
75
- // Stripe API Keys
76
- {
77
- type: 'STRIPE_KEY' as SecretType,
78
- name: 'Stripe API Key',
79
- pattern: /(sk_live_[0-9a-zA-Z]{24,}|pk_live_[0-9a-zA-Z]{24,}|rk_live_[0-9a-zA-Z]{24,})/,
80
- description: 'Stripe Live API Key',
81
- examples: ['sk_live_1234567890abcdefghijklmn'],
82
- },
83
-
84
- // JWT Tokens
85
- {
86
- type: 'JWT_TOKEN' as SecretType,
87
- name: 'JWT Token',
88
- pattern: /(eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]+)/,
89
- minEntropy: 4.0,
90
- description: 'JSON Web Token (JWT)',
91
- examples: ['eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U'],
92
- },
93
-
94
- // Private Keys
95
- {
96
- type: 'PRIVATE_KEY' as SecretType,
97
- name: 'Private Key',
98
- pattern: /(-----BEGIN (RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----[\s\S]*?-----END (RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----)/,
99
- description: 'Private Key (RSA, EC, OpenSSH, DSA)',
100
- examples: ['-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgk...\\n-----END PRIVATE KEY-----'],
101
- },
102
-
103
- // Database URLs with credentials
104
- {
105
- type: 'DATABASE_URL' as SecretType,
106
- name: 'Database URL with Password',
107
- pattern: /(postgres|mysql|mongodb|redis):\/\/[a-zA-Z0-9_-]+:([a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]+)@[a-zA-Z0-9.-]+:[0-9]+/,
108
- minEntropy: 3.0,
109
- description: 'Database connection string with embedded password',
110
- examples: ['postgresql://user:password123@localhost:5432/dbname'],
111
- },
112
-
113
- // Slack Tokens
114
- {
115
- type: 'SLACK_TOKEN' as SecretType,
116
- name: 'Slack Token',
117
- pattern: /(xox[pboa]-[0-9]{10,13}-[0-9]{10,13}-[0-9]{10,13}-[a-z0-9]{32})/,
118
- description: 'Slack Bot/User/App Token',
119
- examples: ['xoxb-0000000000-0000000000-0000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'],
120
- },
121
-
122
- // Generic API Keys (high entropy)
123
- {
124
- type: 'API_KEY_GENERIC' as SecretType,
125
- name: 'Generic API Key',
126
- pattern: /(?:api[_\s-]?key|apikey|access[_\s-]?token|auth[_\s-]?token|secret[_\s-]?key)[_\s]*[=:]\s*['"]?([a-zA-Z0-9_\-]{32,})['"]?/i,
127
- minEntropy: 4.0,
128
- description: 'Generic API key or access token (high entropy)',
129
- examples: ['api_key = abcdef1234567890abcdef1234567890'],
130
- },
131
-
132
- // Generic Passwords
133
- {
134
- type: 'PASSWORD_GENERIC' as SecretType,
135
- name: 'Generic Password',
136
- pattern: /(?:password|passwd|pwd)[_\s]*[=:]\s*['"]([^'"]{8,})['"]|(?:password|passwd|pwd)[_\s]*[=:]\s*([^\s]{8,})/i,
137
- minEntropy: 3.0,
138
- description: 'Generic password in configuration',
139
- examples: ['password = "MySecretP@ssw0rd"'],
140
- },
141
- ];
142
-
143
- /**
144
- * Test/example value patterns (to exclude false positives)
145
- */
146
- export const TEST_PATTERNS = [
147
- /test/i,
148
- /example/i,
149
- /sample/i,
150
- /demo/i,
151
- /fake/i,
152
- /dummy/i,
153
- /placeholder/i,
154
- /\*{3,}/,
155
- /x{3,}/i,
156
- /0{5,}/,
157
- /1{5,}/,
158
- /abc{3,}/i,
159
- /qwerty/i,
160
- /password123/i,
161
- /changeme/i,
162
- /your[_-]?key/i,
163
- /your[_-]?secret/i,
164
- ];
165
-
166
- /**
167
- * Common false positive values
168
- */
169
- export const FALSE_POSITIVE_VALUES = new Set([
170
- 'example',
171
- 'test',
172
- 'sample',
173
- 'demo',
174
- 'placeholder',
175
- 'your_key_here',
176
- 'your_secret_here',
177
- 'xxx',
178
- 'yyy',
179
- 'zzz',
180
- '***',
181
- '000000000000',
182
- '111111111111',
183
- 'abcdefghijklmnopqrstuvwxyz',
184
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
185
- '1234567890',
186
- ]);