guardrail-security 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 (95) hide show
  1. package/dist/attack-surface/analyzer.d.ts +50 -0
  2. package/dist/attack-surface/analyzer.d.ts.map +1 -0
  3. package/dist/attack-surface/analyzer.js +83 -0
  4. package/dist/attack-surface/index.d.ts +5 -0
  5. package/dist/attack-surface/index.d.ts.map +1 -0
  6. package/dist/attack-surface/index.js +20 -0
  7. package/dist/index.d.ts +15 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +33 -0
  10. package/dist/languages/index.d.ts +21 -0
  11. package/dist/languages/index.d.ts.map +1 -0
  12. package/dist/languages/index.js +78 -0
  13. package/dist/languages/java-analyzer.d.ts +72 -0
  14. package/dist/languages/java-analyzer.d.ts.map +1 -0
  15. package/dist/languages/java-analyzer.js +417 -0
  16. package/dist/languages/python-analyzer.d.ts +70 -0
  17. package/dist/languages/python-analyzer.d.ts.map +1 -0
  18. package/dist/languages/python-analyzer.js +425 -0
  19. package/dist/license/compatibility-matrix.d.ts +28 -0
  20. package/dist/license/compatibility-matrix.d.ts.map +1 -0
  21. package/dist/license/compatibility-matrix.js +323 -0
  22. package/dist/license/engine.d.ts +77 -0
  23. package/dist/license/engine.d.ts.map +1 -0
  24. package/dist/license/engine.js +264 -0
  25. package/dist/license/index.d.ts +6 -0
  26. package/dist/license/index.d.ts.map +1 -0
  27. package/dist/license/index.js +21 -0
  28. package/dist/sbom/generator.d.ts +108 -0
  29. package/dist/sbom/generator.d.ts.map +1 -0
  30. package/dist/sbom/generator.js +271 -0
  31. package/dist/sbom/index.d.ts +5 -0
  32. package/dist/sbom/index.d.ts.map +1 -0
  33. package/dist/sbom/index.js +20 -0
  34. package/dist/secrets/guardian.d.ts +113 -0
  35. package/dist/secrets/guardian.d.ts.map +1 -0
  36. package/dist/secrets/guardian.js +334 -0
  37. package/dist/secrets/index.d.ts +10 -0
  38. package/dist/secrets/index.d.ts.map +1 -0
  39. package/dist/secrets/index.js +30 -0
  40. package/dist/secrets/patterns.d.ts +42 -0
  41. package/dist/secrets/patterns.d.ts.map +1 -0
  42. package/dist/secrets/patterns.js +165 -0
  43. package/dist/secrets/pre-commit.d.ts +39 -0
  44. package/dist/secrets/pre-commit.d.ts.map +1 -0
  45. package/dist/secrets/pre-commit.js +127 -0
  46. package/dist/secrets/vault-integration.d.ts +83 -0
  47. package/dist/secrets/vault-integration.d.ts.map +1 -0
  48. package/dist/secrets/vault-integration.js +295 -0
  49. package/dist/secrets/vault-providers.d.ts +110 -0
  50. package/dist/secrets/vault-providers.d.ts.map +1 -0
  51. package/dist/secrets/vault-providers.js +417 -0
  52. package/dist/supply-chain/detector.d.ts +80 -0
  53. package/dist/supply-chain/detector.d.ts.map +1 -0
  54. package/dist/supply-chain/detector.js +168 -0
  55. package/dist/supply-chain/index.d.ts +11 -0
  56. package/dist/supply-chain/index.d.ts.map +1 -0
  57. package/dist/supply-chain/index.js +26 -0
  58. package/dist/supply-chain/malicious-db.d.ts +41 -0
  59. package/dist/supply-chain/malicious-db.d.ts.map +1 -0
  60. package/dist/supply-chain/malicious-db.js +82 -0
  61. package/dist/supply-chain/script-analyzer.d.ts +54 -0
  62. package/dist/supply-chain/script-analyzer.d.ts.map +1 -0
  63. package/dist/supply-chain/script-analyzer.js +160 -0
  64. package/dist/supply-chain/typosquat.d.ts +58 -0
  65. package/dist/supply-chain/typosquat.d.ts.map +1 -0
  66. package/dist/supply-chain/typosquat.js +257 -0
  67. package/dist/supply-chain/vulnerability-db.d.ts +114 -0
  68. package/dist/supply-chain/vulnerability-db.d.ts.map +1 -0
  69. package/dist/supply-chain/vulnerability-db.js +310 -0
  70. package/package.json +34 -0
  71. package/src/__tests__/license/engine.test.ts +250 -0
  72. package/src/__tests__/supply-chain/typosquat.test.ts +191 -0
  73. package/src/attack-surface/analyzer.ts +152 -0
  74. package/src/attack-surface/index.ts +5 -0
  75. package/src/index.ts +21 -0
  76. package/src/languages/index.ts +91 -0
  77. package/src/languages/java-analyzer.ts +490 -0
  78. package/src/languages/python-analyzer.ts +498 -0
  79. package/src/license/compatibility-matrix.ts +366 -0
  80. package/src/license/engine.ts +345 -0
  81. package/src/license/index.ts +6 -0
  82. package/src/sbom/generator.ts +355 -0
  83. package/src/sbom/index.ts +5 -0
  84. package/src/secrets/guardian.ts +448 -0
  85. package/src/secrets/index.ts +10 -0
  86. package/src/secrets/patterns.ts +186 -0
  87. package/src/secrets/pre-commit.ts +158 -0
  88. package/src/secrets/vault-integration.ts +360 -0
  89. package/src/secrets/vault-providers.ts +446 -0
  90. package/src/supply-chain/detector.ts +252 -0
  91. package/src/supply-chain/index.ts +11 -0
  92. package/src/supply-chain/malicious-db.ts +103 -0
  93. package/src/supply-chain/script-analyzer.ts +194 -0
  94. package/src/supply-chain/typosquat.ts +302 -0
  95. package/src/supply-chain/vulnerability-db.ts +386 -0
@@ -0,0 +1,334 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.secretsGuardian = exports.SecretsGuardian = exports.SecretType = void 0;
4
+ const database_1 = require("@guardrail/database");
5
+ const core_1 = require("@guardrail/core");
6
+ const patterns_1 = require("./patterns");
7
+ const fs_1 = require("fs");
8
+ const glob_1 = require("glob");
9
+ const path_1 = require("path");
10
+ // Define SecretType locally since it's not exported from database
11
+ var SecretType;
12
+ (function (SecretType) {
13
+ SecretType["API_KEY"] = "api_key";
14
+ SecretType["PASSWORD"] = "password";
15
+ SecretType["TOKEN"] = "token";
16
+ SecretType["CERTIFICATE"] = "certificate";
17
+ SecretType["PRIVATE_KEY"] = "private_key";
18
+ SecretType["DATABASE_URL"] = "database_url";
19
+ SecretType["JWT_SECRET"] = "jwt_secret";
20
+ SecretType["AWS_ACCESS_KEY"] = "aws_access_key";
21
+ SecretType["OTHER"] = "other";
22
+ SecretType["AWS_SECRET_KEY"] = "aws_secret_key";
23
+ SecretType["GITHUB_TOKEN"] = "github_token";
24
+ SecretType["GOOGLE_API_KEY"] = "google_api_key";
25
+ SecretType["STRIPE_KEY"] = "stripe_key";
26
+ SecretType["JWT_TOKEN"] = "jwt_token";
27
+ SecretType["SLACK_TOKEN"] = "slack_token";
28
+ SecretType["API_KEY_GENERIC"] = "api_key_generic";
29
+ SecretType["PASSWORD_GENERIC"] = "password_generic";
30
+ })(SecretType || (exports.SecretType = SecretType = {}));
31
+ /**
32
+ * Secrets & Credential Guardian
33
+ *
34
+ * Detects exposed secrets and credentials in code
35
+ */
36
+ class SecretsGuardian {
37
+ /**
38
+ * Scan content for secrets
39
+ */
40
+ async scanContent(content, filePath, options = {}) {
41
+ const detections = [];
42
+ const lines = content.split('\n');
43
+ for (const pattern of patterns_1.SECRET_PATTERNS) {
44
+ const matches = [...content.matchAll(new RegExp(pattern.pattern, 'g'))];
45
+ for (const match of matches) {
46
+ if (!match.index)
47
+ continue;
48
+ // Extract the secret value (first capturing group)
49
+ const value = match[1] || match[0];
50
+ // Calculate entropy
51
+ const entropy = this.calculateEntropy(value);
52
+ // Check minimum entropy requirement
53
+ if (pattern.minEntropy && entropy < pattern.minEntropy) {
54
+ continue;
55
+ }
56
+ // Find line number and column
57
+ const beforeMatch = content.substring(0, match.index);
58
+ const lineNumber = beforeMatch.split('\n').length;
59
+ const lineStart = beforeMatch.lastIndexOf('\n') + 1;
60
+ const column = match.index - lineStart + 1;
61
+ // Get context
62
+ const snippet = lines[lineNumber - 1] || '';
63
+ // Check if it's a test value
64
+ const isTest = this.isTestValue(value, snippet);
65
+ // Check for false positives
66
+ const isFalsePositive = this.isFalsePositive(value, pattern.type, snippet);
67
+ if (isFalsePositive) {
68
+ continue;
69
+ }
70
+ // Calculate confidence
71
+ const confidence = this.calculateConfidence(value, pattern, entropy, isTest);
72
+ // Skip if below minimum confidence
73
+ if (options.minConfidence && confidence < options.minConfidence) {
74
+ continue;
75
+ }
76
+ // Skip if excluding tests
77
+ if (options.excludeTests && isTest) {
78
+ continue;
79
+ }
80
+ // Mask the value
81
+ const maskedValue = this.maskValue(value);
82
+ // Generate recommendation
83
+ const recommendation = this.generateRecommendation(pattern.type, isTest);
84
+ // Create detection object
85
+ const detection = {
86
+ id: undefined, // Will be set when saved to database
87
+ filePath,
88
+ secretType: pattern.type,
89
+ maskedValue,
90
+ location: {
91
+ line: lineNumber,
92
+ column,
93
+ snippet: snippet.trim(),
94
+ },
95
+ confidence,
96
+ entropy,
97
+ isTest,
98
+ isRevoked: false,
99
+ recommendation,
100
+ };
101
+ detections.push(detection);
102
+ }
103
+ }
104
+ return detections;
105
+ }
106
+ /**
107
+ * Scan entire project
108
+ */
109
+ async scanProject(projectPath, projectId, options = {}) {
110
+ const excludePatterns = [
111
+ '**/node_modules/**',
112
+ '**/dist/**',
113
+ '**/build/**',
114
+ '**/.git/**',
115
+ '**/coverage/**',
116
+ '**/*.min.js',
117
+ ...(options.excludePatterns || []),
118
+ ];
119
+ // Find all files to scan
120
+ const files = await (0, glob_1.glob)('**/*', {
121
+ cwd: projectPath,
122
+ ignore: excludePatterns,
123
+ nodir: true,
124
+ });
125
+ const allDetections = [];
126
+ let scannedFiles = 0;
127
+ for (const file of files) {
128
+ try {
129
+ const fullPath = (0, path_1.join)(projectPath, file);
130
+ const content = (0, fs_1.readFileSync)(fullPath, 'utf-8');
131
+ const detections = await this.scanContent(content, file, options);
132
+ // Save to database
133
+ for (const detection of detections) {
134
+ try {
135
+ // @ts-ignore - secretDetection may not exist in schema yet
136
+ await database_1.prisma.secretDetection.create({
137
+ data: {
138
+ projectId: 'default',
139
+ filePath: detection.filePath
140
+ }
141
+ });
142
+ }
143
+ catch (error) {
144
+ // Table may not exist - continue
145
+ }
146
+ }
147
+ allDetections.push(...detections);
148
+ scannedFiles++;
149
+ }
150
+ catch (error) {
151
+ // Skip files that can't be read
152
+ continue;
153
+ }
154
+ }
155
+ // Generate summary
156
+ const byType = {};
157
+ const byRisk = { high: 0, medium: 0, low: 0 };
158
+ for (const detection of allDetections) {
159
+ byType[detection.secretType] = (byType[detection.secretType] || 0) + 1;
160
+ if (detection.confidence >= 0.8) {
161
+ byRisk.high++;
162
+ }
163
+ else if (detection.confidence >= 0.5) {
164
+ byRisk.medium++;
165
+ }
166
+ else {
167
+ byRisk.low++;
168
+ }
169
+ }
170
+ return {
171
+ projectId,
172
+ totalFiles: files.length,
173
+ scannedFiles,
174
+ detections: allDetections,
175
+ summary: {
176
+ totalSecrets: allDetections.length,
177
+ byType,
178
+ byRisk,
179
+ },
180
+ };
181
+ }
182
+ /**
183
+ * Calculate entropy for randomness detection
184
+ */
185
+ calculateEntropy(str) {
186
+ return (0, core_1.calculateEntropy)(str);
187
+ }
188
+ /**
189
+ * Check if likely test/example value
190
+ */
191
+ isTestValue(value, context) {
192
+ const lowerValue = value.toLowerCase();
193
+ const lowerContext = context.toLowerCase();
194
+ // Check value itself
195
+ for (const pattern of patterns_1.TEST_PATTERNS) {
196
+ if (pattern.test(lowerValue)) {
197
+ return true;
198
+ }
199
+ }
200
+ // Check context
201
+ if (lowerContext.includes('test') ||
202
+ lowerContext.includes('example') ||
203
+ lowerContext.includes('demo') ||
204
+ lowerContext.includes('fixture') ||
205
+ lowerContext.includes('mock')) {
206
+ return true;
207
+ }
208
+ return false;
209
+ }
210
+ /**
211
+ * Check for false positives
212
+ */
213
+ isFalsePositive(value, type, _context) {
214
+ const lowerValue = value.toLowerCase();
215
+ // Check against known false positives
216
+ if (patterns_1.FALSE_POSITIVE_VALUES.has(lowerValue)) {
217
+ return true;
218
+ }
219
+ // Check for placeholder patterns
220
+ if (/^(x+|0+|1+|a+)$/i.test(value)) {
221
+ return true;
222
+ }
223
+ // Check for repeated characters (likely placeholder)
224
+ if (/(.)\1{10,}/.test(value)) {
225
+ return true;
226
+ }
227
+ // JWT-specific false positive checks
228
+ if (type === SecretType.JWT_TOKEN) {
229
+ // Very simple/short payload might be example
230
+ try {
231
+ const parts = value.split('.');
232
+ if (parts.length === 3 && parts[1]) {
233
+ const payload = Buffer.from(parts[1], 'base64').toString();
234
+ if (payload.length < 20) {
235
+ return true;
236
+ }
237
+ }
238
+ }
239
+ catch {
240
+ // Invalid JWT, might be false positive
241
+ return true;
242
+ }
243
+ }
244
+ return false;
245
+ }
246
+ /**
247
+ * Calculate confidence score
248
+ */
249
+ calculateConfidence(value, pattern, entropy, isTest) {
250
+ let confidence = 0.7; // Base confidence
251
+ // Increase confidence for high entropy
252
+ if (entropy > 4.5) {
253
+ confidence += 0.2;
254
+ }
255
+ else if (entropy > 4.0) {
256
+ confidence += 0.1;
257
+ }
258
+ // Decrease confidence for test values
259
+ if (isTest) {
260
+ confidence -= 0.3;
261
+ }
262
+ // Pattern-specific adjustments
263
+ if (pattern.type === SecretType.AWS_ACCESS_KEY && value.startsWith('AKIA')) {
264
+ confidence += 0.1;
265
+ }
266
+ if (pattern.type === SecretType.GITHUB_TOKEN && /^gh[pos]_/.test(value)) {
267
+ confidence += 0.1;
268
+ }
269
+ return Math.max(0, Math.min(1, confidence));
270
+ }
271
+ /**
272
+ * Mask secret for safe logging
273
+ */
274
+ maskValue(value) {
275
+ return (0, core_1.maskSensitiveValue)(value);
276
+ }
277
+ /**
278
+ * Generate recommendation
279
+ */
280
+ generateRecommendation(type, isTest) {
281
+ if (isTest) {
282
+ return {
283
+ action: 'remove',
284
+ reason: 'Test credential detected in code',
285
+ remediation: 'Remove test credentials and use mocking instead',
286
+ };
287
+ }
288
+ // High-risk secrets require rotation
289
+ const highRiskTypes = [
290
+ 'AWS_SECRET_KEY',
291
+ 'GITHUB_TOKEN',
292
+ 'STRIPE_KEY',
293
+ 'PRIVATE_KEY',
294
+ ];
295
+ if (highRiskTypes.includes(type)) {
296
+ return {
297
+ action: 'revoke_and_rotate',
298
+ reason: 'High-risk credential exposed in code',
299
+ remediation: 'Immediately revoke this credential and rotate to a new one. Store in secure vault or environment variables.',
300
+ };
301
+ }
302
+ // Medium-risk can use env vars
303
+ return {
304
+ action: 'move_to_env',
305
+ reason: 'Credential should not be hardcoded',
306
+ remediation: 'Move to environment variables or secure vault (e.g., AWS Secrets Manager, HashiCorp Vault)',
307
+ };
308
+ }
309
+ /**
310
+ * Get project secrets report
311
+ */
312
+ async getProjectReport(projectId) {
313
+ // @ts-ignore - secretDetection may not exist in schema yet
314
+ const detections = await database_1.prisma.secretDetection.findMany({
315
+ where: { projectId },
316
+ orderBy: { createdAt: 'desc' },
317
+ });
318
+ return detections.map((s) => ({
319
+ id: s.id,
320
+ filePath: s.filePath,
321
+ secretType: s.secretType,
322
+ maskedValue: s.maskedValue,
323
+ location: s.location,
324
+ confidence: s.confidence,
325
+ entropy: s.entropy,
326
+ isTest: s.isTest,
327
+ isRevoked: s.isRevoked,
328
+ recommendation: s.recommendation,
329
+ }));
330
+ }
331
+ }
332
+ exports.SecretsGuardian = SecretsGuardian;
333
+ // Export singleton
334
+ exports.secretsGuardian = new SecretsGuardian();
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Secrets & Credential Guardian
3
+ *
4
+ * Detects and prevents exposure of secrets and credentials
5
+ */
6
+ export * from './patterns';
7
+ export { secretsGuardian, SecretsGuardian } from './guardian';
8
+ export { preCommitHook } from './pre-commit';
9
+ export { vaultIntegration } from './vault-integration';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/secrets/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /**
3
+ * Secrets & Credential Guardian
4
+ *
5
+ * Detects and prevents exposure of secrets and credentials
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.vaultIntegration = exports.preCommitHook = exports.SecretsGuardian = exports.secretsGuardian = void 0;
23
+ __exportStar(require("./patterns"), exports);
24
+ var guardian_1 = require("./guardian");
25
+ Object.defineProperty(exports, "secretsGuardian", { enumerable: true, get: function () { return guardian_1.secretsGuardian; } });
26
+ Object.defineProperty(exports, "SecretsGuardian", { enumerable: true, get: function () { return guardian_1.SecretsGuardian; } });
27
+ var pre_commit_1 = require("./pre-commit");
28
+ Object.defineProperty(exports, "preCommitHook", { enumerable: true, get: function () { return pre_commit_1.preCommitHook; } });
29
+ var vault_integration_1 = require("./vault-integration");
30
+ Object.defineProperty(exports, "vaultIntegration", { enumerable: true, get: function () { return vault_integration_1.vaultIntegration; } });
@@ -0,0 +1,42 @@
1
+ export declare enum SecretType {
2
+ API_KEY = "api_key",
3
+ PASSWORD = "password",
4
+ TOKEN = "token",
5
+ CERTIFICATE = "certificate",
6
+ PRIVATE_KEY = "private_key",
7
+ DATABASE_URL = "database_url",
8
+ JWT_SECRET = "jwt_secret",
9
+ AWS_ACCESS_KEY = "aws_access_key",
10
+ OTHER = "other",
11
+ AWS_SECRET_KEY = "aws_secret_key",
12
+ GITHUB_TOKEN = "github_token",
13
+ GOOGLE_API_KEY = "google_api_key",
14
+ STRIPE_KEY = "stripe_key",
15
+ JWT_TOKEN = "jwt_token",
16
+ SLACK_TOKEN = "slack_token",
17
+ API_KEY_GENERIC = "api_key_generic"
18
+ }
19
+ /**
20
+ * Secret detection pattern
21
+ */
22
+ export interface SecretPattern {
23
+ type: SecretType;
24
+ name: string;
25
+ pattern: RegExp;
26
+ minEntropy?: number;
27
+ description: string;
28
+ examples: string[];
29
+ }
30
+ /**
31
+ * Comprehensive secret detection patterns
32
+ */
33
+ export declare const SECRET_PATTERNS: SecretPattern[];
34
+ /**
35
+ * Test/example value patterns (to exclude false positives)
36
+ */
37
+ export declare const TEST_PATTERNS: RegExp[];
38
+ /**
39
+ * Common false positive values
40
+ */
41
+ export declare const FALSE_POSITIVE_VALUES: Set<string>;
42
+ //# sourceMappingURL=patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/secrets/patterns.ts"],"names":[],"mappings":"AACA,oBAAY,UAAU;IACpB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,UAAU,eAAe;IACzB,cAAc,mBAAmB;IACjC,KAAK,UAAU;IACf,cAAc,mBAAmB;IACjC,YAAY,iBAAiB;IAC7B,cAAc,mBAAmB;IACjC,UAAU,eAAe;IACzB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,eAAe,oBAAoB;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAyG1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,UAkBzB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,aAiBhC,CAAC"}
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FALSE_POSITIVE_VALUES = exports.TEST_PATTERNS = exports.SECRET_PATTERNS = exports.SecretType = void 0;
4
+ // Define SecretType locally since it's not exported from database
5
+ var SecretType;
6
+ (function (SecretType) {
7
+ SecretType["API_KEY"] = "api_key";
8
+ SecretType["PASSWORD"] = "password";
9
+ SecretType["TOKEN"] = "token";
10
+ SecretType["CERTIFICATE"] = "certificate";
11
+ SecretType["PRIVATE_KEY"] = "private_key";
12
+ SecretType["DATABASE_URL"] = "database_url";
13
+ SecretType["JWT_SECRET"] = "jwt_secret";
14
+ SecretType["AWS_ACCESS_KEY"] = "aws_access_key";
15
+ SecretType["OTHER"] = "other";
16
+ SecretType["AWS_SECRET_KEY"] = "aws_secret_key";
17
+ SecretType["GITHUB_TOKEN"] = "github_token";
18
+ SecretType["GOOGLE_API_KEY"] = "google_api_key";
19
+ SecretType["STRIPE_KEY"] = "stripe_key";
20
+ SecretType["JWT_TOKEN"] = "jwt_token";
21
+ SecretType["SLACK_TOKEN"] = "slack_token";
22
+ SecretType["API_KEY_GENERIC"] = "api_key_generic";
23
+ })(SecretType || (exports.SecretType = SecretType = {}));
24
+ /**
25
+ * Comprehensive secret detection patterns
26
+ */
27
+ exports.SECRET_PATTERNS = [
28
+ // AWS Access Keys
29
+ {
30
+ type: 'AWS_ACCESS_KEY',
31
+ name: 'AWS Access Key ID',
32
+ pattern: /(AKIA[0-9A-Z]{16})/,
33
+ minEntropy: 3.5,
34
+ description: 'AWS Access Key ID (starts with AKIA)',
35
+ examples: ['AKIAIOSFODNN7EXAMPLE'],
36
+ },
37
+ // AWS Secret Keys
38
+ {
39
+ type: 'AWS_SECRET_KEY',
40
+ name: 'AWS Secret Access Key',
41
+ pattern: /aws[_\s]*secret[_\s]*access[_\s]*key[_\s]*[=:]\s*['"]?([A-Za-z0-9/+=]{40})['"]?/i,
42
+ minEntropy: 4.5,
43
+ description: 'AWS Secret Access Key (40 characters)',
44
+ examples: ['aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'],
45
+ },
46
+ // GitHub Personal Access Tokens
47
+ {
48
+ type: 'GITHUB_TOKEN',
49
+ name: 'GitHub Personal Access Token',
50
+ 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})/,
51
+ description: 'GitHub Personal Access Token (ghp_, gho_, ghu_, ghs_, ghr_)',
52
+ examples: ['ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'],
53
+ },
54
+ // Google API Keys
55
+ {
56
+ type: 'GOOGLE_API_KEY',
57
+ name: 'Google API Key',
58
+ pattern: /(AIza[0-9A-Za-z\-_]{35})/,
59
+ description: 'Google API Key (starts with AIza)',
60
+ examples: ['AIzaSyDaGmWKa4JsXZ-HjGw7ISLn_3namBGewQe'],
61
+ },
62
+ // Stripe API Keys
63
+ {
64
+ type: 'STRIPE_KEY',
65
+ name: 'Stripe API Key',
66
+ pattern: /(sk_live_[0-9a-zA-Z]{24,}|pk_live_[0-9a-zA-Z]{24,}|rk_live_[0-9a-zA-Z]{24,})/,
67
+ description: 'Stripe Live API Key',
68
+ examples: ['sk_live_1234567890abcdefghijklmn'],
69
+ },
70
+ // JWT Tokens
71
+ {
72
+ type: 'JWT_TOKEN',
73
+ name: 'JWT Token',
74
+ pattern: /(eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]+)/,
75
+ minEntropy: 4.0,
76
+ description: 'JSON Web Token (JWT)',
77
+ examples: ['eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U'],
78
+ },
79
+ // Private Keys
80
+ {
81
+ type: 'PRIVATE_KEY',
82
+ name: 'Private Key',
83
+ pattern: /(-----BEGIN (RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----[\s\S]*?-----END (RSA |EC |OPENSSH |DSA )?PRIVATE KEY-----)/,
84
+ description: 'Private Key (RSA, EC, OpenSSH, DSA)',
85
+ examples: ['-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgk...\\n-----END PRIVATE KEY-----'],
86
+ },
87
+ // Database URLs with credentials
88
+ {
89
+ type: 'DATABASE_URL',
90
+ name: 'Database URL with Password',
91
+ pattern: /(postgres|mysql|mongodb|redis):\/\/[a-zA-Z0-9_-]+:([a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]+)@[a-zA-Z0-9.-]+:[0-9]+/,
92
+ minEntropy: 3.0,
93
+ description: 'Database connection string with embedded password',
94
+ examples: ['postgresql://user:password123@localhost:5432/dbname'],
95
+ },
96
+ // Slack Tokens
97
+ {
98
+ type: 'SLACK_TOKEN',
99
+ name: 'Slack Token',
100
+ pattern: /(xox[pboa]-[0-9]{10,13}-[0-9]{10,13}-[0-9]{10,13}-[a-z0-9]{32})/,
101
+ description: 'Slack Bot/User/App Token',
102
+ examples: ['xoxb-0000000000-0000000000-0000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'],
103
+ },
104
+ // Generic API Keys (high entropy)
105
+ {
106
+ type: 'API_KEY_GENERIC',
107
+ name: 'Generic API Key',
108
+ pattern: /(?:api[_\s-]?key|apikey|access[_\s-]?token|auth[_\s-]?token|secret[_\s-]?key)[_\s]*[=:]\s*['"]?([a-zA-Z0-9_\-]{32,})['"]?/i,
109
+ minEntropy: 4.0,
110
+ description: 'Generic API key or access token (high entropy)',
111
+ examples: ['api_key = abcdef1234567890abcdef1234567890'],
112
+ },
113
+ // Generic Passwords
114
+ {
115
+ type: 'PASSWORD_GENERIC',
116
+ name: 'Generic Password',
117
+ pattern: /(?:password|passwd|pwd)[_\s]*[=:]\s*['"]([^'"]{8,})['"]|(?:password|passwd|pwd)[_\s]*[=:]\s*([^\s]{8,})/i,
118
+ minEntropy: 3.0,
119
+ description: 'Generic password in configuration',
120
+ examples: ['password = "MySecretP@ssw0rd"'],
121
+ },
122
+ ];
123
+ /**
124
+ * Test/example value patterns (to exclude false positives)
125
+ */
126
+ exports.TEST_PATTERNS = [
127
+ /test/i,
128
+ /example/i,
129
+ /sample/i,
130
+ /demo/i,
131
+ /fake/i,
132
+ /dummy/i,
133
+ /placeholder/i,
134
+ /\*{3,}/,
135
+ /x{3,}/i,
136
+ /0{5,}/,
137
+ /1{5,}/,
138
+ /abc{3,}/i,
139
+ /qwerty/i,
140
+ /password123/i,
141
+ /changeme/i,
142
+ /your[_-]?key/i,
143
+ /your[_-]?secret/i,
144
+ ];
145
+ /**
146
+ * Common false positive values
147
+ */
148
+ exports.FALSE_POSITIVE_VALUES = new Set([
149
+ 'example',
150
+ 'test',
151
+ 'sample',
152
+ 'demo',
153
+ 'placeholder',
154
+ 'your_key_here',
155
+ 'your_secret_here',
156
+ 'xxx',
157
+ 'yyy',
158
+ 'zzz',
159
+ '***',
160
+ '000000000000',
161
+ '111111111111',
162
+ 'abcdefghijklmnopqrstuvwxyz',
163
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
164
+ '1234567890',
165
+ ]);
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Staged file info
3
+ */
4
+ export interface StagedFile {
5
+ path: string;
6
+ content: string;
7
+ }
8
+ /**
9
+ * Pre-commit scan result
10
+ */
11
+ export interface PreCommitScanResult {
12
+ passed: boolean;
13
+ detections: number;
14
+ files: string[];
15
+ message: string;
16
+ }
17
+ /**
18
+ * Pre-Commit Hook for Secrets Detection
19
+ */
20
+ export declare class PreCommitHook {
21
+ /**
22
+ * Generate pre-commit hook script
23
+ */
24
+ generateHookScript(): string;
25
+ /**
26
+ * Scan staged files
27
+ */
28
+ scanStagedFiles(gitRoot: string): Promise<PreCommitScanResult>;
29
+ /**
30
+ * Get staged files from git
31
+ */
32
+ private getStagedFiles;
33
+ /**
34
+ * Install pre-commit hook
35
+ */
36
+ installHook(gitRoot: string): void;
37
+ }
38
+ export declare const preCommitHook: PreCommitHook;
39
+ //# sourceMappingURL=pre-commit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pre-commit.d.ts","sourceRoot":"","sources":["../../src/secrets/pre-commit.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAoB5B;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA+CpE;;OAEG;IACH,OAAO,CAAC,cAAc;IAqCtB;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAWnC;AAGD,eAAO,MAAM,aAAa,eAAsB,CAAC"}