driftdetect-core 0.6.1 → 0.7.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/LICENSE +21 -0
- package/dist/constants/analysis/categorizer.d.ts +27 -0
- package/dist/constants/analysis/categorizer.d.ts.map +1 -0
- package/dist/constants/analysis/categorizer.js +364 -0
- package/dist/constants/analysis/categorizer.js.map +1 -0
- package/dist/constants/analysis/consistency-analyzer.d.ts +77 -0
- package/dist/constants/analysis/consistency-analyzer.d.ts.map +1 -0
- package/dist/constants/analysis/consistency-analyzer.js +176 -0
- package/dist/constants/analysis/consistency-analyzer.js.map +1 -0
- package/dist/constants/analysis/dead-constant-detector.d.ts +79 -0
- package/dist/constants/analysis/dead-constant-detector.d.ts.map +1 -0
- package/dist/constants/analysis/dead-constant-detector.js +242 -0
- package/dist/constants/analysis/dead-constant-detector.js.map +1 -0
- package/dist/constants/analysis/magic-detector.d.ts +116 -0
- package/dist/constants/analysis/magic-detector.d.ts.map +1 -0
- package/dist/constants/analysis/magic-detector.js +425 -0
- package/dist/constants/analysis/magic-detector.js.map +1 -0
- package/dist/constants/analysis/reference-finder.d.ts +87 -0
- package/dist/constants/analysis/reference-finder.d.ts.map +1 -0
- package/dist/constants/analysis/reference-finder.js +269 -0
- package/dist/constants/analysis/reference-finder.js.map +1 -0
- package/dist/constants/analysis/security-scanner.d.ts +115 -0
- package/dist/constants/analysis/security-scanner.d.ts.map +1 -0
- package/dist/constants/analysis/security-scanner.js +429 -0
- package/dist/constants/analysis/security-scanner.js.map +1 -0
- package/dist/constants/extractors/base-extractor.d.ts +97 -0
- package/dist/constants/extractors/base-extractor.d.ts.map +1 -0
- package/dist/constants/extractors/base-extractor.js +285 -0
- package/dist/constants/extractors/base-extractor.js.map +1 -0
- package/dist/constants/extractors/regex/base-regex.d.ts +67 -0
- package/dist/constants/extractors/regex/base-regex.d.ts.map +1 -0
- package/dist/constants/extractors/regex/base-regex.js +209 -0
- package/dist/constants/extractors/regex/base-regex.js.map +1 -0
- package/dist/constants/extractors/regex/csharp-regex.d.ts +39 -0
- package/dist/constants/extractors/regex/csharp-regex.d.ts.map +1 -0
- package/dist/constants/extractors/regex/csharp-regex.js +316 -0
- package/dist/constants/extractors/regex/csharp-regex.js.map +1 -0
- package/dist/constants/extractors/regex/go-regex.d.ts +40 -0
- package/dist/constants/extractors/regex/go-regex.d.ts.map +1 -0
- package/dist/constants/extractors/regex/go-regex.js +297 -0
- package/dist/constants/extractors/regex/go-regex.js.map +1 -0
- package/dist/constants/extractors/regex/java-regex.d.ts +43 -0
- package/dist/constants/extractors/regex/java-regex.d.ts.map +1 -0
- package/dist/constants/extractors/regex/java-regex.js +276 -0
- package/dist/constants/extractors/regex/java-regex.js.map +1 -0
- package/dist/constants/extractors/regex/php-regex.d.ts +39 -0
- package/dist/constants/extractors/regex/php-regex.d.ts.map +1 -0
- package/dist/constants/extractors/regex/php-regex.js +270 -0
- package/dist/constants/extractors/regex/php-regex.js.map +1 -0
- package/dist/constants/extractors/regex/python-regex.d.ts +39 -0
- package/dist/constants/extractors/regex/python-regex.d.ts.map +1 -0
- package/dist/constants/extractors/regex/python-regex.js +287 -0
- package/dist/constants/extractors/regex/python-regex.js.map +1 -0
- package/dist/constants/extractors/regex/typescript-regex.d.ts +35 -0
- package/dist/constants/extractors/regex/typescript-regex.d.ts.map +1 -0
- package/dist/constants/extractors/regex/typescript-regex.js +313 -0
- package/dist/constants/extractors/regex/typescript-regex.js.map +1 -0
- package/dist/constants/index.d.ts +26 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +36 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/constants/integration/callgraph-adapter.d.ts +167 -0
- package/dist/constants/integration/callgraph-adapter.d.ts.map +1 -0
- package/dist/constants/integration/callgraph-adapter.js +287 -0
- package/dist/constants/integration/callgraph-adapter.js.map +1 -0
- package/dist/constants/integration/index.d.ts +10 -0
- package/dist/constants/integration/index.d.ts.map +1 -0
- package/dist/constants/integration/index.js +13 -0
- package/dist/constants/integration/index.js.map +1 -0
- package/dist/constants/integration/pattern-adapter.d.ts +171 -0
- package/dist/constants/integration/pattern-adapter.d.ts.map +1 -0
- package/dist/constants/integration/pattern-adapter.js +331 -0
- package/dist/constants/integration/pattern-adapter.js.map +1 -0
- package/dist/constants/integration/scanner-adapter.d.ts +153 -0
- package/dist/constants/integration/scanner-adapter.d.ts.map +1 -0
- package/dist/constants/integration/scanner-adapter.js +337 -0
- package/dist/constants/integration/scanner-adapter.js.map +1 -0
- package/dist/constants/store/constant-store.d.ts +117 -0
- package/dist/constants/store/constant-store.d.ts.map +1 -0
- package/dist/constants/store/constant-store.js +367 -0
- package/dist/constants/store/constant-store.js.map +1 -0
- package/dist/constants/types.d.ts +423 -0
- package/dist/constants/types.d.ts.map +1 -0
- package/dist/constants/types.js +43 -0
- package/dist/constants/types.js.map +1 -0
- package/dist/environment/env-scanner.d.ts +53 -0
- package/dist/environment/env-scanner.d.ts.map +1 -0
- package/dist/environment/env-scanner.js +290 -0
- package/dist/environment/env-scanner.js.map +1 -0
- package/dist/environment/env-store.d.ts +70 -0
- package/dist/environment/env-store.d.ts.map +1 -0
- package/dist/environment/env-store.js +201 -0
- package/dist/environment/env-store.js.map +1 -0
- package/dist/environment/extractors/base-env-extractor.d.ts +56 -0
- package/dist/environment/extractors/base-env-extractor.d.ts.map +1 -0
- package/dist/environment/extractors/base-env-extractor.js +74 -0
- package/dist/environment/extractors/base-env-extractor.js.map +1 -0
- package/dist/environment/extractors/csharp-env-extractor.d.ts +49 -0
- package/dist/environment/extractors/csharp-env-extractor.d.ts.map +1 -0
- package/dist/environment/extractors/csharp-env-extractor.js +240 -0
- package/dist/environment/extractors/csharp-env-extractor.js.map +1 -0
- package/dist/environment/extractors/go-env-extractor.d.ts +53 -0
- package/dist/environment/extractors/go-env-extractor.d.ts.map +1 -0
- package/dist/environment/extractors/go-env-extractor.js +267 -0
- package/dist/environment/extractors/go-env-extractor.js.map +1 -0
- package/dist/environment/extractors/index.d.ts +13 -0
- package/dist/environment/extractors/index.d.ts.map +1 -0
- package/dist/environment/extractors/index.js +13 -0
- package/dist/environment/extractors/index.js.map +1 -0
- package/dist/environment/extractors/java-env-extractor.d.ts +58 -0
- package/dist/environment/extractors/java-env-extractor.d.ts.map +1 -0
- package/dist/environment/extractors/java-env-extractor.js +219 -0
- package/dist/environment/extractors/java-env-extractor.js.map +1 -0
- package/dist/environment/extractors/php-env-extractor.d.ts +58 -0
- package/dist/environment/extractors/php-env-extractor.d.ts.map +1 -0
- package/dist/environment/extractors/php-env-extractor.js +231 -0
- package/dist/environment/extractors/php-env-extractor.js.map +1 -0
- package/dist/environment/extractors/python-env-extractor.d.ts +50 -0
- package/dist/environment/extractors/python-env-extractor.d.ts.map +1 -0
- package/dist/environment/extractors/python-env-extractor.js +219 -0
- package/dist/environment/extractors/python-env-extractor.js.map +1 -0
- package/dist/environment/extractors/typescript-env-extractor.d.ts +54 -0
- package/dist/environment/extractors/typescript-env-extractor.d.ts.map +1 -0
- package/dist/environment/extractors/typescript-env-extractor.js +228 -0
- package/dist/environment/extractors/typescript-env-extractor.js.map +1 -0
- package/dist/environment/index.d.ts +11 -0
- package/dist/environment/index.d.ts.map +1 -0
- package/dist/environment/index.js +15 -0
- package/dist/environment/index.js.map +1 -0
- package/dist/environment/types.d.ts +145 -0
- package/dist/environment/types.d.ts.map +1 -0
- package/dist/environment/types.js +84 -0
- package/dist/environment/types.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -1
- package/package.json +13 -13
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Scanner for Constants
|
|
3
|
+
*
|
|
4
|
+
* Detects potential hardcoded secrets, credentials, and sensitive
|
|
5
|
+
* values in constants.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Default security scan config
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_SECURITY_SCAN_CONFIG = {
|
|
11
|
+
enableEntropyDetection: true,
|
|
12
|
+
entropyThreshold: 4.5,
|
|
13
|
+
customPatterns: [],
|
|
14
|
+
allowlistPatterns: [
|
|
15
|
+
'**/test/**',
|
|
16
|
+
'**/*.test.*',
|
|
17
|
+
'**/*.spec.*',
|
|
18
|
+
'**/mock/**',
|
|
19
|
+
'**/fixture/**',
|
|
20
|
+
],
|
|
21
|
+
allowlistValues: [
|
|
22
|
+
/^test/i,
|
|
23
|
+
/^mock/i,
|
|
24
|
+
/^fake/i,
|
|
25
|
+
/^dummy/i,
|
|
26
|
+
/^example/i,
|
|
27
|
+
/^placeholder/i,
|
|
28
|
+
/^xxx+$/i,
|
|
29
|
+
/^\*+$/,
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Built-in secret patterns
|
|
34
|
+
*/
|
|
35
|
+
const BUILTIN_PATTERNS = [
|
|
36
|
+
// API Keys
|
|
37
|
+
{
|
|
38
|
+
name: 'AWS Access Key',
|
|
39
|
+
valuePattern: /^AKIA[0-9A-Z]{16}$/,
|
|
40
|
+
type: 'aws_key',
|
|
41
|
+
severity: 'critical',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'AWS Secret Key',
|
|
45
|
+
namePattern: /aws.*secret/i,
|
|
46
|
+
type: 'aws_key',
|
|
47
|
+
severity: 'critical',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'Stripe API Key',
|
|
51
|
+
valuePattern: /^sk_(?:live|test)_[0-9a-zA-Z]{24,}$/,
|
|
52
|
+
type: 'stripe_key',
|
|
53
|
+
severity: 'critical',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'Stripe Publishable Key',
|
|
57
|
+
valuePattern: /^pk_(?:live|test)_[0-9a-zA-Z]{24,}$/,
|
|
58
|
+
type: 'stripe_key',
|
|
59
|
+
severity: 'medium',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'GitHub Token',
|
|
63
|
+
valuePattern: /^gh[pousr]_[A-Za-z0-9_]{36,}$/,
|
|
64
|
+
type: 'github_token',
|
|
65
|
+
severity: 'critical',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'GitHub Personal Access Token',
|
|
69
|
+
valuePattern: /^github_pat_[A-Za-z0-9_]{22,}$/,
|
|
70
|
+
type: 'github_token',
|
|
71
|
+
severity: 'critical',
|
|
72
|
+
},
|
|
73
|
+
// Generic patterns by name
|
|
74
|
+
{
|
|
75
|
+
name: 'API Key',
|
|
76
|
+
namePattern: /(?:api[_-]?key|apikey)/i,
|
|
77
|
+
type: 'api_key',
|
|
78
|
+
severity: 'high',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'Secret Key',
|
|
82
|
+
namePattern: /(?:secret[_-]?key|secretkey)/i,
|
|
83
|
+
type: 'secret_key',
|
|
84
|
+
severity: 'high',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'Password',
|
|
88
|
+
namePattern: /(?:password|passwd|pwd)/i,
|
|
89
|
+
type: 'password',
|
|
90
|
+
severity: 'critical',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'Private Key',
|
|
94
|
+
namePattern: /(?:private[_-]?key|privatekey)/i,
|
|
95
|
+
type: 'private_key',
|
|
96
|
+
severity: 'critical',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Access Token',
|
|
100
|
+
namePattern: /(?:access[_-]?token|accesstoken)/i,
|
|
101
|
+
type: 'token',
|
|
102
|
+
severity: 'high',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'Auth Token',
|
|
106
|
+
namePattern: /(?:auth[_-]?token|authtoken)/i,
|
|
107
|
+
type: 'token',
|
|
108
|
+
severity: 'high',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'Bearer Token',
|
|
112
|
+
namePattern: /(?:bearer[_-]?token|bearertoken)/i,
|
|
113
|
+
type: 'token',
|
|
114
|
+
severity: 'high',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'Refresh Token',
|
|
118
|
+
namePattern: /(?:refresh[_-]?token|refreshtoken)/i,
|
|
119
|
+
type: 'token',
|
|
120
|
+
severity: 'high',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'Connection String',
|
|
124
|
+
namePattern: /(?:connection[_-]?string|connstring|conn[_-]?str)/i,
|
|
125
|
+
type: 'connection_string',
|
|
126
|
+
severity: 'critical',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'Database URL',
|
|
130
|
+
namePattern: /(?:database[_-]?url|db[_-]?url)/i,
|
|
131
|
+
type: 'connection_string',
|
|
132
|
+
severity: 'critical',
|
|
133
|
+
},
|
|
134
|
+
// Value patterns
|
|
135
|
+
{
|
|
136
|
+
name: 'Private Key Block',
|
|
137
|
+
valuePattern: /-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/,
|
|
138
|
+
type: 'private_key',
|
|
139
|
+
severity: 'critical',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'Certificate',
|
|
143
|
+
valuePattern: /-----BEGIN CERTIFICATE-----/,
|
|
144
|
+
type: 'certificate',
|
|
145
|
+
severity: 'high',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'Connection String with Password',
|
|
149
|
+
valuePattern: /(?:mongodb|mysql|postgres|redis):\/\/[^:]+:[^@]+@/i,
|
|
150
|
+
type: 'connection_string',
|
|
151
|
+
severity: 'critical',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'Basic Auth Header',
|
|
155
|
+
valuePattern: /^Basic [A-Za-z0-9+/=]{10,}$/,
|
|
156
|
+
type: 'token',
|
|
157
|
+
severity: 'high',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: 'Bearer Auth Header',
|
|
161
|
+
valuePattern: /^Bearer [A-Za-z0-9._-]{10,}$/,
|
|
162
|
+
type: 'token',
|
|
163
|
+
severity: 'high',
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
/**
|
|
167
|
+
* Security scanner for constants
|
|
168
|
+
*/
|
|
169
|
+
export class ConstantSecurityScanner {
|
|
170
|
+
config;
|
|
171
|
+
patterns;
|
|
172
|
+
constructor(config = {}) {
|
|
173
|
+
this.config = { ...DEFAULT_SECURITY_SCAN_CONFIG, ...config };
|
|
174
|
+
this.patterns = [...BUILTIN_PATTERNS, ...this.config.customPatterns];
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Scan constants for potential secrets
|
|
178
|
+
*/
|
|
179
|
+
scan(constants) {
|
|
180
|
+
const startTime = performance.now();
|
|
181
|
+
const secrets = [];
|
|
182
|
+
const bySeverity = {
|
|
183
|
+
info: 0,
|
|
184
|
+
low: 0,
|
|
185
|
+
medium: 0,
|
|
186
|
+
high: 0,
|
|
187
|
+
critical: 0,
|
|
188
|
+
};
|
|
189
|
+
for (const constant of constants) {
|
|
190
|
+
// Skip allowlisted files
|
|
191
|
+
if (this.isAllowlistedFile(constant.file)) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
// Skip if value is allowlisted
|
|
195
|
+
if (this.isAllowlistedValue(constant.value)) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const secret = this.analyzeConstant(constant);
|
|
199
|
+
if (secret) {
|
|
200
|
+
secrets.push(secret);
|
|
201
|
+
bySeverity[secret.severity]++;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Sort by severity (critical first)
|
|
205
|
+
const severityOrder = ['critical', 'high', 'medium', 'low', 'info'];
|
|
206
|
+
secrets.sort((a, b) => severityOrder.indexOf(a.severity) - severityOrder.indexOf(b.severity));
|
|
207
|
+
return {
|
|
208
|
+
secrets,
|
|
209
|
+
totalScanned: constants.length,
|
|
210
|
+
scanTimeMs: performance.now() - startTime,
|
|
211
|
+
bySeverity,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Analyze a single constant for secrets
|
|
216
|
+
*/
|
|
217
|
+
analyzeConstant(constant) {
|
|
218
|
+
const value = constant.value;
|
|
219
|
+
const valueStr = typeof value === 'string' ? value : String(value ?? '');
|
|
220
|
+
// Check against patterns
|
|
221
|
+
for (const pattern of this.patterns) {
|
|
222
|
+
// Check name pattern
|
|
223
|
+
if (pattern.namePattern && pattern.namePattern.test(constant.name)) {
|
|
224
|
+
// Only flag if value looks like a real secret (not empty/placeholder)
|
|
225
|
+
if (this.looksLikeRealSecret(valueStr)) {
|
|
226
|
+
return this.createSecret(constant, pattern.type, pattern.severity, pattern.name);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Check value pattern
|
|
230
|
+
if (pattern.valuePattern && pattern.valuePattern.test(valueStr)) {
|
|
231
|
+
return this.createSecret(constant, pattern.type, pattern.severity, pattern.name);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Entropy-based detection for string values
|
|
235
|
+
if (this.config.enableEntropyDetection && typeof value === 'string') {
|
|
236
|
+
const entropy = this.calculateEntropy(value);
|
|
237
|
+
if (entropy >= this.config.entropyThreshold && value.length >= 16) {
|
|
238
|
+
// High entropy string - might be a secret
|
|
239
|
+
// Check if name suggests it's a secret
|
|
240
|
+
if (this.nameSuggestsSecret(constant.name)) {
|
|
241
|
+
return this.createSecret(constant, 'generic_secret', 'medium', `High entropy value (${entropy.toFixed(2)})`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Create a potential secret object
|
|
249
|
+
*/
|
|
250
|
+
createSecret(constant, type, severity, _detectedBy) {
|
|
251
|
+
const value = constant.value;
|
|
252
|
+
const valueStr = typeof value === 'string' ? value : String(value ?? '');
|
|
253
|
+
return {
|
|
254
|
+
constantId: constant.id,
|
|
255
|
+
name: constant.name,
|
|
256
|
+
file: constant.file,
|
|
257
|
+
line: constant.line,
|
|
258
|
+
maskedValue: this.maskValue(valueStr),
|
|
259
|
+
secretType: type,
|
|
260
|
+
severity,
|
|
261
|
+
recommendation: this.generateRecommendation(type, constant.name),
|
|
262
|
+
confidence: this.calculateConfidence(constant, type),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Mask a value for safe display
|
|
267
|
+
*/
|
|
268
|
+
maskValue(value) {
|
|
269
|
+
if (value.length <= 8) {
|
|
270
|
+
return '*'.repeat(value.length);
|
|
271
|
+
}
|
|
272
|
+
const visibleChars = Math.min(4, Math.floor(value.length / 4));
|
|
273
|
+
const start = value.slice(0, visibleChars);
|
|
274
|
+
const end = value.slice(-visibleChars);
|
|
275
|
+
const masked = '*'.repeat(Math.min(20, value.length - visibleChars * 2));
|
|
276
|
+
return `${start}${masked}${end}`;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Generate recommendation for a secret type
|
|
280
|
+
*/
|
|
281
|
+
generateRecommendation(type, name) {
|
|
282
|
+
const recommendations = {
|
|
283
|
+
api_key: `Move '${name}' to environment variables or a secrets manager.`,
|
|
284
|
+
secret_key: `Move '${name}' to environment variables or a secrets manager.`,
|
|
285
|
+
password: `Never hardcode passwords. Use environment variables or a secrets manager.`,
|
|
286
|
+
private_key: `Private keys should never be in source code. Use a secrets manager or key vault.`,
|
|
287
|
+
connection_string: `Move '${name}' to environment variables. Consider using a secrets manager.`,
|
|
288
|
+
token: `Move '${name}' to environment variables or implement token refresh.`,
|
|
289
|
+
certificate: `Certificates should be loaded from files or a certificate store, not hardcoded.`,
|
|
290
|
+
aws_key: `Use IAM roles or AWS Secrets Manager instead of hardcoded AWS credentials.`,
|
|
291
|
+
stripe_key: `Move Stripe keys to environment variables. Use restricted keys in production.`,
|
|
292
|
+
github_token: `Use GitHub Apps or environment variables instead of hardcoded tokens.`,
|
|
293
|
+
generic_secret: `This value appears to be a secret. Move it to environment variables.`,
|
|
294
|
+
};
|
|
295
|
+
return recommendations[type] || `Consider moving '${name}' to a secure configuration.`;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Calculate confidence score for a detection
|
|
299
|
+
*/
|
|
300
|
+
calculateConfidence(constant, type) {
|
|
301
|
+
let confidence = 0.5;
|
|
302
|
+
// Higher confidence for specific patterns
|
|
303
|
+
if (['aws_key', 'stripe_key', 'github_token'].includes(type)) {
|
|
304
|
+
confidence = 0.95;
|
|
305
|
+
}
|
|
306
|
+
else if (['private_key', 'certificate'].includes(type)) {
|
|
307
|
+
confidence = 0.9;
|
|
308
|
+
}
|
|
309
|
+
else if (['password', 'connection_string'].includes(type)) {
|
|
310
|
+
confidence = 0.85;
|
|
311
|
+
}
|
|
312
|
+
else if (['api_key', 'secret_key', 'token'].includes(type)) {
|
|
313
|
+
confidence = 0.75;
|
|
314
|
+
}
|
|
315
|
+
// Lower confidence if in test file
|
|
316
|
+
if (this.isTestFile(constant.file)) {
|
|
317
|
+
confidence *= 0.5;
|
|
318
|
+
}
|
|
319
|
+
// Lower confidence if value looks like placeholder
|
|
320
|
+
const value = String(constant.value ?? '');
|
|
321
|
+
if (this.looksLikePlaceholder(value)) {
|
|
322
|
+
confidence *= 0.3;
|
|
323
|
+
}
|
|
324
|
+
return Math.min(1, Math.max(0, confidence));
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Check if a value looks like a real secret (not placeholder)
|
|
328
|
+
*/
|
|
329
|
+
looksLikeRealSecret(value) {
|
|
330
|
+
if (!value || value.length < 8)
|
|
331
|
+
return false;
|
|
332
|
+
// Check for placeholder patterns
|
|
333
|
+
if (this.looksLikePlaceholder(value))
|
|
334
|
+
return false;
|
|
335
|
+
// Check for reasonable entropy
|
|
336
|
+
const entropy = this.calculateEntropy(value);
|
|
337
|
+
return entropy >= 2.5;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Check if a value looks like a placeholder
|
|
341
|
+
*/
|
|
342
|
+
looksLikePlaceholder(value) {
|
|
343
|
+
const lower = value.toLowerCase();
|
|
344
|
+
return (lower.includes('xxx') ||
|
|
345
|
+
lower.includes('placeholder') ||
|
|
346
|
+
lower.includes('example') ||
|
|
347
|
+
lower.includes('your_') ||
|
|
348
|
+
lower.includes('your-') ||
|
|
349
|
+
lower.includes('<your') ||
|
|
350
|
+
lower.includes('[your') ||
|
|
351
|
+
lower.includes('changeme') ||
|
|
352
|
+
lower.includes('todo') ||
|
|
353
|
+
lower.includes('fixme') ||
|
|
354
|
+
/^[a-z]+$/.test(lower) || // Single word
|
|
355
|
+
/^[x*]+$/.test(lower) // All x's or asterisks
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Check if name suggests it might be a secret
|
|
360
|
+
*/
|
|
361
|
+
nameSuggestsSecret(name) {
|
|
362
|
+
const lower = name.toLowerCase();
|
|
363
|
+
return (lower.includes('key') ||
|
|
364
|
+
lower.includes('secret') ||
|
|
365
|
+
lower.includes('token') ||
|
|
366
|
+
lower.includes('password') ||
|
|
367
|
+
lower.includes('credential') ||
|
|
368
|
+
lower.includes('auth'));
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Calculate Shannon entropy of a string
|
|
372
|
+
*/
|
|
373
|
+
calculateEntropy(str) {
|
|
374
|
+
if (!str || str.length === 0)
|
|
375
|
+
return 0;
|
|
376
|
+
const freq = new Map();
|
|
377
|
+
for (const char of str) {
|
|
378
|
+
freq.set(char, (freq.get(char) || 0) + 1);
|
|
379
|
+
}
|
|
380
|
+
let entropy = 0;
|
|
381
|
+
const len = str.length;
|
|
382
|
+
for (const count of freq.values()) {
|
|
383
|
+
const p = count / len;
|
|
384
|
+
entropy -= p * Math.log2(p);
|
|
385
|
+
}
|
|
386
|
+
return entropy;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Check if file is allowlisted
|
|
390
|
+
*/
|
|
391
|
+
isAllowlistedFile(filePath) {
|
|
392
|
+
for (const pattern of this.config.allowlistPatterns) {
|
|
393
|
+
// Simple glob matching
|
|
394
|
+
const regex = pattern
|
|
395
|
+
.replace(/\*\*/g, '.*')
|
|
396
|
+
.replace(/\*/g, '[^/]*')
|
|
397
|
+
.replace(/\?/g, '.');
|
|
398
|
+
if (new RegExp(regex).test(filePath)) {
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Check if value is allowlisted
|
|
406
|
+
*/
|
|
407
|
+
isAllowlistedValue(value) {
|
|
408
|
+
if (typeof value !== 'string')
|
|
409
|
+
return false;
|
|
410
|
+
for (const pattern of this.config.allowlistValues) {
|
|
411
|
+
if (pattern.test(value)) {
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Check if file is a test file
|
|
419
|
+
*/
|
|
420
|
+
isTestFile(filePath) {
|
|
421
|
+
return (filePath.includes('.test.') ||
|
|
422
|
+
filePath.includes('.spec.') ||
|
|
423
|
+
filePath.includes('__tests__') ||
|
|
424
|
+
filePath.includes('__mocks__') ||
|
|
425
|
+
filePath.includes('/test/') ||
|
|
426
|
+
filePath.includes('/tests/'));
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
//# sourceMappingURL=security-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-scanner.js","sourceRoot":"","sources":["../../../src/constants/analysis/security-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Constant Extractor
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class for hybrid constant extractors that combine
|
|
5
|
+
* tree-sitter (primary) with regex fallback for enterprise-grade coverage.
|
|
6
|
+
*
|
|
7
|
+
* Follows the same pattern as call-graph/extractors/hybrid-extractor-base.ts
|
|
8
|
+
*/
|
|
9
|
+
import type { ConstantLanguage, FileConstantResult, ConstantExtractionQuality, ConstantHybridConfig } from '../types.js';
|
|
10
|
+
import type { BaseConstantRegexExtractor } from './regex/base-regex.js';
|
|
11
|
+
/**
|
|
12
|
+
* Abstract base class for hybrid constant extractors
|
|
13
|
+
*/
|
|
14
|
+
export declare abstract class BaseConstantExtractor {
|
|
15
|
+
/** Language this extractor handles */
|
|
16
|
+
abstract readonly language: ConstantLanguage;
|
|
17
|
+
/** File extensions this extractor handles */
|
|
18
|
+
abstract readonly extensions: string[];
|
|
19
|
+
/** Configuration */
|
|
20
|
+
protected config: Required<ConstantHybridConfig>;
|
|
21
|
+
/** Regex fallback extractor */
|
|
22
|
+
protected abstract regexExtractor: BaseConstantRegexExtractor;
|
|
23
|
+
constructor(config?: ConstantHybridConfig);
|
|
24
|
+
/**
|
|
25
|
+
* Check if this extractor can handle a file
|
|
26
|
+
*/
|
|
27
|
+
canHandle(filePath: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Extract constants with hybrid approach: tree-sitter first, regex fallback
|
|
30
|
+
*/
|
|
31
|
+
extract(source: string, filePath: string): FileConstantResult;
|
|
32
|
+
/**
|
|
33
|
+
* Extract using tree-sitter (implemented by subclass)
|
|
34
|
+
*/
|
|
35
|
+
protected abstract extractWithTreeSitter(source: string, filePath: string): FileConstantResult | null;
|
|
36
|
+
/**
|
|
37
|
+
* Check if tree-sitter is available for this language
|
|
38
|
+
*/
|
|
39
|
+
protected abstract isTreeSitterAvailable(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Extract with regex fallback, merging with tree-sitter results
|
|
42
|
+
*/
|
|
43
|
+
private extractWithFallback;
|
|
44
|
+
/**
|
|
45
|
+
* Extract using regex only
|
|
46
|
+
*/
|
|
47
|
+
private extractWithRegexOnly;
|
|
48
|
+
/**
|
|
49
|
+
* Merge tree-sitter and regex results
|
|
50
|
+
*/
|
|
51
|
+
private mergeResults;
|
|
52
|
+
/**
|
|
53
|
+
* Merge constants, avoiding duplicates
|
|
54
|
+
*/
|
|
55
|
+
private mergeUniqueConstants;
|
|
56
|
+
/**
|
|
57
|
+
* Merge enums, avoiding duplicates
|
|
58
|
+
*/
|
|
59
|
+
private mergeUniqueEnums;
|
|
60
|
+
/**
|
|
61
|
+
* Merge references, avoiding duplicates
|
|
62
|
+
*/
|
|
63
|
+
private mergeUniqueReferences;
|
|
64
|
+
/**
|
|
65
|
+
* Check if extraction result has good coverage
|
|
66
|
+
*/
|
|
67
|
+
private hasGoodCoverage;
|
|
68
|
+
/**
|
|
69
|
+
* Create quality metrics for tree-sitter extraction
|
|
70
|
+
*/
|
|
71
|
+
private createTreeSitterQuality;
|
|
72
|
+
/**
|
|
73
|
+
* Create merged quality metrics
|
|
74
|
+
*/
|
|
75
|
+
private createMergedQuality;
|
|
76
|
+
/**
|
|
77
|
+
* Create error result
|
|
78
|
+
*/
|
|
79
|
+
private createErrorResult;
|
|
80
|
+
/**
|
|
81
|
+
* Create empty result
|
|
82
|
+
*/
|
|
83
|
+
private createEmptyResult;
|
|
84
|
+
/**
|
|
85
|
+
* Get file extension
|
|
86
|
+
*/
|
|
87
|
+
protected getExtension(filePath: string): string;
|
|
88
|
+
/**
|
|
89
|
+
* Generate constant ID
|
|
90
|
+
*/
|
|
91
|
+
protected generateConstantId(file: string, name: string, line: number): string;
|
|
92
|
+
/**
|
|
93
|
+
* Create default quality metrics
|
|
94
|
+
*/
|
|
95
|
+
protected createDefaultQuality(): ConstantExtractionQuality;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=base-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-extractor.d.ts","sourceRoot":"","sources":["../../../src/constants/extractors/base-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAIlB,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAKrB,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAExE;;GAEG;AACH,8BAAsB,qBAAqB;IACzC,sCAAsC;IACtC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IAE7C,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;IAEvC,oBAAoB;IACpB,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IAEjD,+BAA+B;IAC/B,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,0BAA0B,CAAC;gBAElD,MAAM,CAAC,EAAE,oBAAoB;IAIzC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKpC;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,kBAAkB;IAgD7D;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,qBAAqB,CACtC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,kBAAkB,GAAG,IAAI;IAE5B;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,qBAAqB,IAAI,OAAO;IAEnD;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAuB5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAepB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAkB5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkB7B;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA2BzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqBzB;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAKhD;;OAEG;IACH,SAAS,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAI9E;;OAEG;IACH,SAAS,CAAC,oBAAoB,IAAI,yBAAyB;CAY5D"}
|