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,158 +0,0 @@
1
- import { secretsGuardian } from './guardian';
2
- import { execSync } from 'child_process';
3
- import { writeFileSync } from 'fs';
4
- import { join } from 'path';
5
-
6
- /**
7
- * Staged file info
8
- */
9
- export interface StagedFile {
10
- path: string;
11
- content: string;
12
- }
13
-
14
- /**
15
- * Pre-commit scan result
16
- */
17
- export interface PreCommitScanResult {
18
- passed: boolean;
19
- detections: number;
20
- files: string[];
21
- message: string;
22
- }
23
-
24
- /**
25
- * Pre-Commit Hook for Secrets Detection
26
- */
27
- export class PreCommitHook {
28
- /**
29
- * Generate pre-commit hook script
30
- */
31
- generateHookScript(): string {
32
- return `#!/bin/bash
33
- # Guardrail Secrets Detection Pre-Commit Hook
34
-
35
- echo "🔍 Scanning for secrets..."
36
-
37
- # Run secrets scan via API or CLI
38
- npx Guardrail secrets scan-staged
39
-
40
- if [ $? -ne 0 ]; then
41
- echo "❌ Secrets detected! Commit blocked."
42
- echo "Please remove secrets or add to .gitignore"
43
- exit 1
44
- fi
45
-
46
- echo "✅ No secrets detected"
47
- exit 0
48
- `;
49
- }
50
-
51
- /**
52
- * Scan staged files
53
- */
54
- async scanStagedFiles(gitRoot: string): Promise<PreCommitScanResult> {
55
- try {
56
- // Get staged files
57
- const stagedFiles = this.getStagedFiles(gitRoot);
58
-
59
- if (stagedFiles.length === 0) {
60
- return {
61
- passed: true,
62
- detections: 0,
63
- files: [],
64
- message: 'No files to scan',
65
- };
66
- }
67
-
68
- // Scan each staged file
69
- const allDetections: string[] = [];
70
-
71
- for (const file of stagedFiles) {
72
- const detections = await secretsGuardian.scanContent(
73
- file.content,
74
- file.path,
75
- {
76
- excludeTests: true,
77
- minConfidence: 0.7,
78
- }
79
- );
80
-
81
- if (detections.length > 0) {
82
- allDetections.push(file.path);
83
- }
84
- }
85
-
86
- const passed = allDetections.length === 0;
87
-
88
- return {
89
- passed,
90
- detections: allDetections.length,
91
- files: allDetections,
92
- message: passed
93
- ? 'No secrets detected in staged files'
94
- : `Secrets detected in ${allDetections.length} file(s)`,
95
- };
96
- } catch (error) {
97
- throw new Error(`Pre-commit scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
98
- }
99
- }
100
-
101
- /**
102
- * Get staged files from git
103
- */
104
- private getStagedFiles(gitRoot: string): StagedFile[] {
105
- try {
106
- // Get list of staged files
107
- const output = execSync('git diff --cached --name-only --diff-filter=ACM', {
108
- cwd: gitRoot,
109
- encoding: 'utf-8',
110
- });
111
-
112
- const filePaths = output.trim().split('\n').filter((f) => f);
113
-
114
- // Read content of each staged file
115
- const stagedFiles: StagedFile[] = [];
116
-
117
- for (const filePath of filePaths) {
118
- try {
119
- // Get staged content (not working directory)
120
- const content = execSync(`git show :${filePath}`, {
121
- cwd: gitRoot,
122
- encoding: 'utf-8',
123
- });
124
-
125
- stagedFiles.push({
126
- path: filePath,
127
- content,
128
- });
129
- } catch (error) {
130
- // File might be deleted or binary, skip
131
- continue;
132
- }
133
- }
134
-
135
- return stagedFiles;
136
- } catch (error) {
137
- throw new Error(`Failed to get staged files: ${error instanceof Error ? error.message : 'Unknown error'}`);
138
- }
139
- }
140
-
141
- /**
142
- * Install pre-commit hook
143
- */
144
- installHook(gitRoot: string): void {
145
- const hookPath = join(gitRoot, '.git', 'hooks', 'pre-commit');
146
- const hookScript = this.generateHookScript();
147
-
148
- try {
149
- writeFileSync(hookPath, hookScript, { mode: 0o755 });
150
- console.log('✅ Pre-commit hook installed successfully');
151
- } catch (error) {
152
- throw new Error(`Failed to install hook: ${error instanceof Error ? error.message : 'Unknown error'}`);
153
- }
154
- }
155
- }
156
-
157
- // Export singleton
158
- export const preCommitHook = new PreCommitHook();
@@ -1,360 +0,0 @@
1
- import { SecretDetection } from './guardian';
2
- import { SecretType } from './patterns';
3
- import { createVaultProvider, VaultProvider, VaultProviderConfig, LocalEnvProvider } from './vault-providers';
4
-
5
- /**
6
- * Vault configuration
7
- */
8
- export interface VaultConfig {
9
- type: 'aws_secrets_manager' | 'hashicorp_vault' | 'azure_keyvault' | 'gcp_secret_manager';
10
- endpoint?: string;
11
- region?: string;
12
- credentials?: {
13
- accessKeyId?: string;
14
- secretAccessKey?: string;
15
- token?: string;
16
- };
17
- }
18
-
19
- /**
20
- * Migration result
21
- */
22
- export interface VaultMigrationResult {
23
- secretId: string;
24
- vaultId: string;
25
- envVarName: string;
26
- migrated: boolean;
27
- error?: string;
28
- }
29
-
30
- /**
31
- * Vault Integration for Secrets
32
- *
33
- * Helps migrate hardcoded secrets to secure vaults.
34
- * Supports AWS Secrets Manager, HashiCorp Vault, Azure Key Vault, and GCP Secret Manager.
35
- */
36
- export class VaultIntegration {
37
- private providerCache: Map<string, VaultProvider> = new Map();
38
-
39
- /**
40
- * Get or create a vault provider
41
- */
42
- private getProvider(vaultConfig: VaultConfig): VaultProvider {
43
- const cacheKey = `${vaultConfig.type}_${vaultConfig.endpoint || 'default'}`;
44
-
45
- if (!this.providerCache.has(cacheKey)) {
46
- const providerConfig: VaultProviderConfig = {
47
- type: vaultConfig.type,
48
- region: vaultConfig.region,
49
- endpoint: vaultConfig.endpoint,
50
- credentials: vaultConfig.credentials,
51
- };
52
-
53
- try {
54
- const provider = createVaultProvider(providerConfig);
55
- this.providerCache.set(cacheKey, provider);
56
- } catch (error) {
57
- console.warn(`Failed to create vault provider, falling back to local: ${error}`);
58
- this.providerCache.set(cacheKey, new LocalEnvProvider());
59
- }
60
- }
61
-
62
- return this.providerCache.get(cacheKey)!;
63
- }
64
-
65
- /**
66
- * Test vault connection
67
- */
68
- async testConnection(vaultConfig: VaultConfig): Promise<{ connected: boolean; error?: string }> {
69
- try {
70
- const provider = this.getProvider(vaultConfig);
71
- const connected = await provider.testConnection();
72
- return { connected };
73
- } catch (error) {
74
- return {
75
- connected: false,
76
- error: error instanceof Error ? error.message : 'Unknown error'
77
- };
78
- }
79
- }
80
- /**
81
- * Migrate secrets to vault
82
- * Now uses real vault providers instead of simulation
83
- */
84
- async migrateToVault(
85
- detections: SecretDetection[],
86
- vaultConfig: VaultConfig
87
- ): Promise<VaultMigrationResult[]> {
88
- const results: VaultMigrationResult[] = [];
89
- const provider = this.getProvider(vaultConfig);
90
-
91
- // Test connection first
92
- const connectionTest = await this.testConnection(vaultConfig);
93
- if (!connectionTest.connected) {
94
- return detections.map(detection => ({
95
- secretId: detection.id || '',
96
- vaultId: '',
97
- envVarName: this.generateEnvVarName(detection),
98
- migrated: false,
99
- error: `Vault connection failed: ${connectionTest.error}`,
100
- }));
101
- }
102
-
103
- for (const detection of detections) {
104
- try {
105
- const envVarName = this.generateEnvVarName(detection);
106
-
107
- // Extract the actual secret value from detection
108
- // Note: For security, the actual value should be extracted during scan
109
- // maskedValue contains the masked version, snippet contains context
110
- const secretValue = (detection as any).rawValue || detection.location.snippet || '';
111
-
112
- if (!secretValue) {
113
- results.push({
114
- secretId: detection.id || '',
115
- vaultId: '',
116
- envVarName,
117
- migrated: false,
118
- error: 'No secret value found in detection',
119
- });
120
- continue;
121
- }
122
-
123
- // Upload to real vault
124
- const vaultId = await provider.createSecret(envVarName, secretValue);
125
-
126
- results.push({
127
- secretId: detection.id || '',
128
- vaultId,
129
- envVarName,
130
- migrated: true,
131
- });
132
- } catch (error) {
133
- results.push({
134
- secretId: detection.id || '',
135
- vaultId: '',
136
- envVarName: this.generateEnvVarName(detection),
137
- migrated: false,
138
- error: error instanceof Error ? error.message : 'Unknown error',
139
- });
140
- }
141
- }
142
-
143
- return results;
144
- }
145
-
146
- /**
147
- * Retrieve a secret from vault
148
- */
149
- async getSecret(vaultConfig: VaultConfig, secretName: string): Promise<string | null> {
150
- const provider = this.getProvider(vaultConfig);
151
- return provider.getSecret(secretName);
152
- }
153
-
154
- /**
155
- * List all secrets in vault
156
- */
157
- async listSecrets(vaultConfig: VaultConfig): Promise<string[]> {
158
- const provider = this.getProvider(vaultConfig);
159
- return provider.listSecrets();
160
- }
161
-
162
- /**
163
- * Delete a secret from vault
164
- */
165
- async deleteSecret(vaultConfig: VaultConfig, secretName: string): Promise<boolean> {
166
- const provider = this.getProvider(vaultConfig);
167
- return provider.deleteSecret(secretName);
168
- }
169
-
170
- /**
171
- * Generate environment variable name
172
- */
173
- generateEnvVarName(detection: SecretDetection): string {
174
- const typeMap: Record<SecretType, string> = {
175
- [SecretType.AWS_ACCESS_KEY]: 'AWS_ACCESS_KEY_ID',
176
- [SecretType.AWS_SECRET_KEY]: 'AWS_SECRET_ACCESS_KEY',
177
- [SecretType.GITHUB_TOKEN]: 'GITHUB_TOKEN',
178
- [SecretType.GOOGLE_API_KEY]: 'GOOGLE_API_KEY',
179
- [SecretType.STRIPE_KEY]: 'STRIPE_SECRET_KEY',
180
- [SecretType.JWT_TOKEN]: 'JWT_SECRET',
181
- [SecretType.PRIVATE_KEY]: 'PRIVATE_KEY',
182
- [SecretType.DATABASE_URL]: 'DATABASE_URL',
183
- [SecretType.SLACK_TOKEN]: 'SLACK_TOKEN',
184
- [SecretType.API_KEY_GENERIC]: 'API_KEY',
185
- [SecretType.API_KEY]: 'API_KEY',
186
- [SecretType.TOKEN]: 'TOKEN',
187
- [SecretType.CERTIFICATE]: 'CERTIFICATE',
188
- [SecretType.JWT_SECRET]: 'JWT_SECRET',
189
- [SecretType.PASSWORD]: 'PASSWORD',
190
- [SecretType.OTHER]: 'SECRET'
191
- };
192
-
193
- const baseName = typeMap[detection.secretType as SecretType] || 'SECRET';
194
-
195
- // Add file-based suffix if multiple of same type
196
- const fileName = detection.filePath.split('/').pop()?.replace(/[^a-zA-Z0-9]/g, '_').toUpperCase();
197
-
198
- return `${baseName}_${fileName}`;
199
- }
200
-
201
- /**
202
- * Generate code snippet for accessing secret from vault
203
- */
204
- generateCodeSnippet(vaultConfig: VaultConfig, envVarName: string): string {
205
- switch (vaultConfig.type) {
206
- case 'aws_secrets_manager':
207
- return `
208
- // AWS Secrets Manager
209
- import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager";
210
-
211
- const client = new SecretsManagerClient({ region: "${vaultConfig.region || 'us-east-1'}" });
212
- const response = await client.send(
213
- new GetSecretValueCommand({ SecretId: "${envVarName}" })
214
- );
215
- const secret = response.SecretString;
216
- `;
217
-
218
- case 'hashicorp_vault':
219
- return `
220
- // HashiCorp Vault
221
- import vault from "node-vault";
222
-
223
- const vaultClient = vault({
224
- endpoint: "${vaultConfig.endpoint || 'http://127.0.0.1:8200'}",
225
- token: process.env.VAULT_TOKEN
226
- });
227
-
228
- const { data } = await vaultClient.read("secret/data/${envVarName}");
229
- const secret = data.data.value;
230
- `;
231
-
232
- case 'azure_keyvault':
233
- return `
234
- // Azure Key Vault
235
- import { SecretClient } from "@azure/keyvault-secrets";
236
- import { DefaultAzureCredential } from "@azure/identity";
237
-
238
- const credential = new DefaultAzureCredential();
239
- const client = new SecretClient("${vaultConfig.endpoint}", credential);
240
- const secret = await client.getSecret("${envVarName}");
241
- const value = secret.value;
242
- `;
243
-
244
- case 'gcp_secret_manager':
245
- return `
246
- // GCP Secret Manager
247
- import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
248
-
249
- const client = new SecretManagerServiceClient();
250
- const [version] = await client.accessSecretVersion({
251
- name: 'projects/PROJECT_ID/secrets/${envVarName}/versions/latest',
252
- });
253
- const secret = version.payload?.data?.toString();
254
- `;
255
-
256
- default:
257
- return `// Use environment variable: process.env.${envVarName}`;
258
- }
259
- }
260
-
261
- /**
262
- * Generate migration guide
263
- */
264
- generateMigrationGuide(results: VaultMigrationResult[]): string {
265
- let guide = '# Secrets Migration Guide\n\n';
266
- guide += '## Detected Secrets\n\n';
267
-
268
- for (const result of results) {
269
- guide += `### ${result.envVarName}\n`;
270
- guide += `- Vault ID: ${result.vaultId}\n`;
271
- guide += `- Status: ${result.migrated ? '✅ Migrated' : '❌ Failed'}\n`;
272
-
273
- if (result.error) {
274
- guide += `- Error: ${result.error}\n`;
275
- }
276
-
277
- guide += '\n';
278
- }
279
-
280
- guide += '## Next Steps\n\n';
281
- guide += '1. Update your code to fetch secrets from vault\n';
282
- guide += '2. Remove hardcoded secrets from source code\n';
283
- guide += '3. Update CI/CD pipelines to use vault credentials\n';
284
- guide += '4. Test the integration\n';
285
- guide += '5. Commit and push changes\n';
286
-
287
- return guide;
288
- }
289
-
290
- /**
291
- * Verify a secret exists in vault
292
- */
293
- async verifySecret(vaultConfig: VaultConfig, secretName: string): Promise<boolean> {
294
- const secret = await this.getSecret(vaultConfig, secretName);
295
- return secret !== null;
296
- }
297
-
298
- /**
299
- * Batch migrate with progress callback
300
- */
301
- async migrateWithProgress(
302
- detections: SecretDetection[],
303
- vaultConfig: VaultConfig,
304
- onProgress?: (completed: number, total: number, current: string) => void
305
- ): Promise<VaultMigrationResult[]> {
306
- const results: VaultMigrationResult[] = [];
307
- const provider = this.getProvider(vaultConfig);
308
- const total = detections.length;
309
-
310
- for (let i = 0; i < detections.length; i++) {
311
- const detection = detections[i];
312
- if (!detection) continue;
313
-
314
- const envVarName = this.generateEnvVarName(detection);
315
-
316
- if (onProgress) {
317
- onProgress(i, total, envVarName);
318
- }
319
-
320
- try {
321
- const secretValue = (detection as any).rawValue || detection.location.snippet || '';
322
- if (!secretValue) {
323
- results.push({
324
- secretId: detection.id || '',
325
- vaultId: '',
326
- envVarName,
327
- migrated: false,
328
- error: 'No secret value found',
329
- });
330
- continue;
331
- }
332
-
333
- const vaultId = await provider.createSecret(envVarName, secretValue);
334
- results.push({
335
- secretId: detection.id || '',
336
- vaultId,
337
- envVarName,
338
- migrated: true,
339
- });
340
- } catch (error) {
341
- results.push({
342
- secretId: detection.id || '',
343
- vaultId: '',
344
- envVarName,
345
- migrated: false,
346
- error: error instanceof Error ? error.message : 'Unknown error',
347
- });
348
- }
349
- }
350
-
351
- if (onProgress) {
352
- onProgress(total, total, 'Complete');
353
- }
354
-
355
- return results;
356
- }
357
- }
358
-
359
- // Export singleton
360
- export const vaultIntegration = new VaultIntegration();