verification-layer 0.20.0 → 0.22.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/README.md +251 -615
- package/dist/cli.js +542 -0
- package/dist/cli.js.map +1 -1
- package/dist/marketplace/index.d.ts +8 -0
- package/dist/marketplace/index.d.ts.map +1 -0
- package/dist/marketplace/index.js +7 -0
- package/dist/marketplace/index.js.map +1 -0
- package/dist/marketplace/installer.d.ts +62 -0
- package/dist/marketplace/installer.d.ts.map +1 -0
- package/dist/marketplace/installer.js +254 -0
- package/dist/marketplace/installer.js.map +1 -0
- package/dist/marketplace/registry.d.ts +52 -0
- package/dist/marketplace/registry.d.ts.map +1 -0
- package/dist/marketplace/registry.js +759 -0
- package/dist/marketplace/registry.js.map +1 -0
- package/dist/marketplace/types.d.ts +123 -0
- package/dist/marketplace/types.d.ts.map +1 -0
- package/dist/marketplace/types.js +6 -0
- package/dist/marketplace/types.js.map +1 -0
- package/dist/reporters/audit-report.d.ts.map +1 -1
- package/dist/reporters/audit-report.js +180 -0
- package/dist/reporters/audit-report.js.map +1 -1
- package/dist/reporters/index.d.ts.map +1 -1
- package/dist/reporters/index.js +2612 -5
- package/dist/reporters/index.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +15 -1
- package/dist/scan.js.map +1 -1
- package/dist/scanners/api-security/index.d.ts +7 -0
- package/dist/scanners/api-security/index.d.ts.map +1 -0
- package/dist/scanners/api-security/index.js +139 -0
- package/dist/scanners/api-security/index.js.map +1 -0
- package/dist/scanners/api-security/index.test.d.ts +5 -0
- package/dist/scanners/api-security/index.test.d.ts.map +1 -0
- package/dist/scanners/api-security/index.test.js +360 -0
- package/dist/scanners/api-security/index.test.js.map +1 -0
- package/dist/scanners/api-security/patterns.d.ts +32 -0
- package/dist/scanners/api-security/patterns.d.ts.map +1 -0
- package/dist/scanners/api-security/patterns.js +159 -0
- package/dist/scanners/api-security/patterns.js.map +1 -0
- package/dist/scanners/authentication/index.d.ts +7 -0
- package/dist/scanners/authentication/index.d.ts.map +1 -0
- package/dist/scanners/authentication/index.js +107 -0
- package/dist/scanners/authentication/index.js.map +1 -0
- package/dist/scanners/authentication/index.test.d.ts +5 -0
- package/dist/scanners/authentication/index.test.d.ts.map +1 -0
- package/dist/scanners/authentication/index.test.js +379 -0
- package/dist/scanners/authentication/index.test.js.map +1 -0
- package/dist/scanners/authentication/patterns.d.ts +32 -0
- package/dist/scanners/authentication/patterns.d.ts.map +1 -0
- package/dist/scanners/authentication/patterns.js +133 -0
- package/dist/scanners/authentication/patterns.js.map +1 -0
- package/dist/scanners/configuration/index.d.ts +8 -0
- package/dist/scanners/configuration/index.d.ts.map +1 -0
- package/dist/scanners/configuration/index.js +87 -0
- package/dist/scanners/configuration/index.js.map +1 -0
- package/dist/scanners/configuration/index.test.d.ts +5 -0
- package/dist/scanners/configuration/index.test.d.ts.map +1 -0
- package/dist/scanners/configuration/index.test.js +344 -0
- package/dist/scanners/configuration/index.test.js.map +1 -0
- package/dist/scanners/configuration/patterns.d.ts +32 -0
- package/dist/scanners/configuration/patterns.d.ts.map +1 -0
- package/dist/scanners/configuration/patterns.js +146 -0
- package/dist/scanners/configuration/patterns.js.map +1 -0
- package/dist/scanners/credentials/index.d.ts +7 -0
- package/dist/scanners/credentials/index.d.ts.map +1 -0
- package/dist/scanners/credentials/index.js +129 -0
- package/dist/scanners/credentials/index.js.map +1 -0
- package/dist/scanners/credentials/index.test.d.ts +5 -0
- package/dist/scanners/credentials/index.test.d.ts.map +1 -0
- package/dist/scanners/credentials/index.test.js +395 -0
- package/dist/scanners/credentials/index.test.js.map +1 -0
- package/dist/scanners/credentials/patterns.d.ts +32 -0
- package/dist/scanners/credentials/patterns.d.ts.map +1 -0
- package/dist/scanners/credentials/patterns.js +140 -0
- package/dist/scanners/credentials/patterns.js.map +1 -0
- package/dist/scanners/errors/index.d.ts +8 -0
- package/dist/scanners/errors/index.d.ts.map +1 -0
- package/dist/scanners/errors/index.js +78 -0
- package/dist/scanners/errors/index.js.map +1 -0
- package/dist/scanners/errors/index.test.d.ts +5 -0
- package/dist/scanners/errors/index.test.d.ts.map +1 -0
- package/dist/scanners/errors/index.test.js +330 -0
- package/dist/scanners/errors/index.test.js.map +1 -0
- package/dist/scanners/errors/patterns.d.ts +27 -0
- package/dist/scanners/errors/patterns.d.ts.map +1 -0
- package/dist/scanners/errors/patterns.js +97 -0
- package/dist/scanners/errors/patterns.js.map +1 -0
- package/dist/scanners/hipaa2026/index.d.ts +8 -0
- package/dist/scanners/hipaa2026/index.d.ts.map +1 -0
- package/dist/scanners/hipaa2026/index.js +345 -0
- package/dist/scanners/hipaa2026/index.js.map +1 -0
- package/dist/scanners/hipaa2026/index.test.d.ts +5 -0
- package/dist/scanners/hipaa2026/index.test.d.ts.map +1 -0
- package/dist/scanners/hipaa2026/index.test.js +332 -0
- package/dist/scanners/hipaa2026/index.test.js.map +1 -0
- package/dist/scanners/hipaa2026/patterns.d.ts +57 -0
- package/dist/scanners/hipaa2026/patterns.d.ts.map +1 -0
- package/dist/scanners/hipaa2026/patterns.js +268 -0
- package/dist/scanners/hipaa2026/patterns.js.map +1 -0
- package/dist/scanners/operational/index.d.ts +7 -0
- package/dist/scanners/operational/index.d.ts.map +1 -0
- package/dist/scanners/operational/index.js +171 -0
- package/dist/scanners/operational/index.js.map +1 -0
- package/dist/scanners/operational/index.test.d.ts +5 -0
- package/dist/scanners/operational/index.test.d.ts.map +1 -0
- package/dist/scanners/operational/index.test.js +406 -0
- package/dist/scanners/operational/index.test.js.map +1 -0
- package/dist/scanners/operational/patterns.d.ts +33 -0
- package/dist/scanners/operational/patterns.d.ts.map +1 -0
- package/dist/scanners/operational/patterns.js +151 -0
- package/dist/scanners/operational/patterns.js.map +1 -0
- package/dist/scanners/rbac/index.d.ts +7 -0
- package/dist/scanners/rbac/index.d.ts.map +1 -0
- package/dist/scanners/rbac/index.js +145 -0
- package/dist/scanners/rbac/index.js.map +1 -0
- package/dist/scanners/rbac/index.test.d.ts +5 -0
- package/dist/scanners/rbac/index.test.d.ts.map +1 -0
- package/dist/scanners/rbac/index.test.js +422 -0
- package/dist/scanners/rbac/index.test.js.map +1 -0
- package/dist/scanners/rbac/patterns.d.ts +32 -0
- package/dist/scanners/rbac/patterns.d.ts.map +1 -0
- package/dist/scanners/rbac/patterns.js +124 -0
- package/dist/scanners/rbac/patterns.js.map +1 -0
- package/dist/scanners/revocation/index.d.ts +8 -0
- package/dist/scanners/revocation/index.d.ts.map +1 -0
- package/dist/scanners/revocation/index.js +83 -0
- package/dist/scanners/revocation/index.js.map +1 -0
- package/dist/scanners/revocation/index.test.d.ts +5 -0
- package/dist/scanners/revocation/index.test.d.ts.map +1 -0
- package/dist/scanners/revocation/index.test.js +332 -0
- package/dist/scanners/revocation/index.test.js.map +1 -0
- package/dist/scanners/revocation/patterns.d.ts +27 -0
- package/dist/scanners/revocation/patterns.d.ts.map +1 -0
- package/dist/scanners/revocation/patterns.js +109 -0
- package/dist/scanners/revocation/patterns.js.map +1 -0
- package/dist/scanners/sanitization/index.d.ts +8 -0
- package/dist/scanners/sanitization/index.d.ts.map +1 -0
- package/dist/scanners/sanitization/index.js +98 -0
- package/dist/scanners/sanitization/index.js.map +1 -0
- package/dist/scanners/sanitization/index.test.d.ts +5 -0
- package/dist/scanners/sanitization/index.test.d.ts.map +1 -0
- package/dist/scanners/sanitization/index.test.js +370 -0
- package/dist/scanners/sanitization/index.test.js.map +1 -0
- package/dist/scanners/sanitization/patterns.d.ts +27 -0
- package/dist/scanners/sanitization/patterns.d.ts.map +1 -0
- package/dist/scanners/sanitization/patterns.js +117 -0
- package/dist/scanners/sanitization/patterns.js.map +1 -0
- package/dist/training/certificate.d.ts +26 -0
- package/dist/training/certificate.d.ts.map +1 -0
- package/dist/training/certificate.js +92 -0
- package/dist/training/certificate.js.map +1 -0
- package/dist/training/index.d.ts +3 -0
- package/dist/training/index.d.ts.map +1 -0
- package/dist/training/index.js +243 -0
- package/dist/training/index.js.map +1 -0
- package/dist/training/modules.d.ts +13 -0
- package/dist/training/modules.d.ts.map +1 -0
- package/dist/training/modules.js +608 -0
- package/dist/training/modules.js.map +1 -0
- package/dist/training/questions.d.ts +9 -0
- package/dist/training/questions.d.ts.map +1 -0
- package/dist/training/questions.js +505 -0
- package/dist/training/questions.js.map +1 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/npm-audit.d.ts +6 -0
- package/dist/utils/npm-audit.d.ts.map +1 -0
- package/dist/utils/npm-audit.js +95 -0
- package/dist/utils/npm-audit.js.map +1 -0
- package/dist/utils/scan-history.d.ts +59 -0
- package/dist/utils/scan-history.d.ts.map +1 -0
- package/dist/utils/scan-history.js +170 -0
- package/dist/utils/scan-history.js.map +1 -0
- package/package.json +4 -1
- package/templates/baa-verification-letter.md +105 -0
- package/templates/irp.md +545 -0
- package/templates/notice-of-privacy-practices.md +491 -0
- package/templates/physical-safeguards-checklist.md +247 -0
- package/templates/security-officer-designation.md +237 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Credential Security Scanner
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
5
|
+
import { credentialsScanner } from './index.js';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import * as os from 'os';
|
|
9
|
+
describe('Credentials Scanner', () => {
|
|
10
|
+
let tempDir = '';
|
|
11
|
+
let testFiles = [];
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cred-test-'));
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
// Cleanup
|
|
17
|
+
for (const file of testFiles) {
|
|
18
|
+
try {
|
|
19
|
+
await fs.unlink(file);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Ignore
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Ignore
|
|
30
|
+
}
|
|
31
|
+
testFiles = [];
|
|
32
|
+
});
|
|
33
|
+
async function createTestFile(filename, content) {
|
|
34
|
+
const filePath = path.join(tempDir, filename);
|
|
35
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
36
|
+
testFiles.push(filePath);
|
|
37
|
+
return filePath;
|
|
38
|
+
}
|
|
39
|
+
const scanOptions = {
|
|
40
|
+
path: tempDir,
|
|
41
|
+
};
|
|
42
|
+
describe('CRED-001: Weak Password Hashing', () => {
|
|
43
|
+
it('should detect MD5 for password hashing', async () => {
|
|
44
|
+
const file = await createTestFile('auth.ts', `
|
|
45
|
+
import crypto from 'crypto';
|
|
46
|
+
|
|
47
|
+
function hashPassword(password: string) {
|
|
48
|
+
const hash = crypto.createHash('md5');
|
|
49
|
+
hash.update(password);
|
|
50
|
+
return hash.digest('hex');
|
|
51
|
+
}
|
|
52
|
+
`);
|
|
53
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
54
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-001');
|
|
55
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
56
|
+
expect(credFindings[0].severity).toBe('critical');
|
|
57
|
+
expect(credFindings[0].hipaaReference).toContain('164.312(d)');
|
|
58
|
+
});
|
|
59
|
+
it('should detect SHA1 for password hashing', async () => {
|
|
60
|
+
const file = await createTestFile('password.ts', `
|
|
61
|
+
const passwordHash = crypto.createHash('sha1').update(userPassword).digest('hex');
|
|
62
|
+
`);
|
|
63
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
64
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-001');
|
|
65
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
66
|
+
});
|
|
67
|
+
it('should detect SHA256 for password hashing', async () => {
|
|
68
|
+
const file = await createTestFile('user-auth.ts', `
|
|
69
|
+
async function verifyPassword(password: string, hash: string) {
|
|
70
|
+
const computed = crypto.createHash('sha256').update(password).digest('hex');
|
|
71
|
+
return computed === hash;
|
|
72
|
+
}
|
|
73
|
+
`);
|
|
74
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
75
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-001');
|
|
76
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
77
|
+
});
|
|
78
|
+
it('should detect Python hashlib.md5 for passwords', async () => {
|
|
79
|
+
const file = await createTestFile('auth.py', `
|
|
80
|
+
import hashlib
|
|
81
|
+
|
|
82
|
+
def hash_password(password):
|
|
83
|
+
return hashlib.md5(password.encode()).hexdigest()
|
|
84
|
+
`);
|
|
85
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
86
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-001');
|
|
87
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
88
|
+
});
|
|
89
|
+
it('should not flag bcrypt for password hashing', async () => {
|
|
90
|
+
const file = await createTestFile('secure-auth.ts', `
|
|
91
|
+
import bcrypt from 'bcrypt';
|
|
92
|
+
|
|
93
|
+
async function hashPassword(password: string) {
|
|
94
|
+
const hash = await bcrypt.hash(password, 10);
|
|
95
|
+
return hash;
|
|
96
|
+
}
|
|
97
|
+
`);
|
|
98
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
99
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-001');
|
|
100
|
+
expect(credFindings.length).toBe(0);
|
|
101
|
+
});
|
|
102
|
+
it('should not flag argon2 for password hashing', async () => {
|
|
103
|
+
const file = await createTestFile('argon-auth.ts', `
|
|
104
|
+
import argon2 from 'argon2';
|
|
105
|
+
|
|
106
|
+
async function hashPassword(password: string) {
|
|
107
|
+
return await argon2.hash(password);
|
|
108
|
+
}
|
|
109
|
+
`);
|
|
110
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
111
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-001');
|
|
112
|
+
expect(credFindings.length).toBe(0);
|
|
113
|
+
});
|
|
114
|
+
it('should not flag MD5 for file checksum', async () => {
|
|
115
|
+
const file = await createTestFile('checksum.ts', `
|
|
116
|
+
function calculateChecksum(fileBuffer: Buffer) {
|
|
117
|
+
return crypto.createHash('md5').update(fileBuffer).digest('hex');
|
|
118
|
+
}
|
|
119
|
+
`);
|
|
120
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
121
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-001');
|
|
122
|
+
expect(credFindings.length).toBe(0);
|
|
123
|
+
});
|
|
124
|
+
it('should not flag MD5 for integrity check', async () => {
|
|
125
|
+
const file = await createTestFile('integrity.ts', `
|
|
126
|
+
const hash = crypto.createHash('md5');
|
|
127
|
+
hash.update(fileContent);
|
|
128
|
+
const integrity = hash.digest('hex');
|
|
129
|
+
`);
|
|
130
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
131
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-001');
|
|
132
|
+
expect(credFindings.length).toBe(0);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
describe('CRED-002: Hardcoded Credentials', () => {
|
|
136
|
+
it('should detect hardcoded password', async () => {
|
|
137
|
+
const file = await createTestFile('config.ts', `
|
|
138
|
+
const config = {
|
|
139
|
+
username: 'admin',
|
|
140
|
+
password: 'SuperSecret123!'
|
|
141
|
+
};
|
|
142
|
+
`);
|
|
143
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
144
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
145
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
146
|
+
expect(credFindings[0].severity).toBe('critical');
|
|
147
|
+
});
|
|
148
|
+
it('should detect hardcoded API key', async () => {
|
|
149
|
+
const file = await createTestFile('api.ts', `
|
|
150
|
+
const apiKey = 'fake_key_ABCDEFGH1234567890XXXXXX';
|
|
151
|
+
`);
|
|
152
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
153
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
154
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
155
|
+
});
|
|
156
|
+
it('should detect hardcoded secret', async () => {
|
|
157
|
+
const file = await createTestFile('secrets.ts', `
|
|
158
|
+
export const JWT_SECRET = 'my-super-secret-jwt-key-12345';
|
|
159
|
+
`);
|
|
160
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
161
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
162
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
163
|
+
});
|
|
164
|
+
it('should detect hardcoded token', async () => {
|
|
165
|
+
const file = await createTestFile('auth-token.ts', `
|
|
166
|
+
const accessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0';
|
|
167
|
+
`);
|
|
168
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
169
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
170
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
171
|
+
});
|
|
172
|
+
it('should detect hardcoded connection string', async () => {
|
|
173
|
+
const file = await createTestFile('database.ts', `
|
|
174
|
+
const connectionString = 'postgresql://user:password@localhost:5432/mydb';
|
|
175
|
+
`);
|
|
176
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
177
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
178
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
179
|
+
});
|
|
180
|
+
it('should detect Bearer token', async () => {
|
|
181
|
+
const file = await createTestFile('bearer.ts', `
|
|
182
|
+
const token = 'Bearer fake_test_1234567890abcdefghijklmnop';
|
|
183
|
+
`);
|
|
184
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
185
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
186
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
187
|
+
});
|
|
188
|
+
it('should not flag environment variables', async () => {
|
|
189
|
+
const file = await createTestFile('env-config.ts', `
|
|
190
|
+
const password = process.env.DATABASE_PASSWORD;
|
|
191
|
+
const apiKey = process.env.API_KEY;
|
|
192
|
+
`);
|
|
193
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
194
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
195
|
+
expect(credFindings.length).toBe(0);
|
|
196
|
+
});
|
|
197
|
+
it('should not flag import.meta.env', async () => {
|
|
198
|
+
const file = await createTestFile('vite-config.ts', `
|
|
199
|
+
const secret = import.meta.env.VITE_API_KEY;
|
|
200
|
+
`);
|
|
201
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
202
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
203
|
+
expect(credFindings.length).toBe(0);
|
|
204
|
+
});
|
|
205
|
+
it('should not flag placeholders', async () => {
|
|
206
|
+
const file = await createTestFile('example.ts', `
|
|
207
|
+
const apiKey = 'your-api-key-here';
|
|
208
|
+
const password = 'changeme';
|
|
209
|
+
const secret = 'replace-this-value';
|
|
210
|
+
`);
|
|
211
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
212
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
213
|
+
expect(credFindings.length).toBe(0);
|
|
214
|
+
});
|
|
215
|
+
it('should not flag template literals', async () => {
|
|
216
|
+
const file = await createTestFile('template.ts', `
|
|
217
|
+
const connectionString = \`postgresql://\${user}:\${password}@localhost/db\`;
|
|
218
|
+
`);
|
|
219
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
220
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
221
|
+
expect(credFindings.length).toBe(0);
|
|
222
|
+
});
|
|
223
|
+
it('should not flag short or generic passwords', async () => {
|
|
224
|
+
const file = await createTestFile('generic.ts', `
|
|
225
|
+
const password = 'test';
|
|
226
|
+
const pwd = '12345';
|
|
227
|
+
`);
|
|
228
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
229
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
230
|
+
expect(credFindings.length).toBe(0);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
describe('CRED-003: NEXT_PUBLIC_ Secrets', () => {
|
|
234
|
+
it('should detect NEXT_PUBLIC_SECRET', async () => {
|
|
235
|
+
const file = await createTestFile('.env.local', `
|
|
236
|
+
NEXT_PUBLIC_SECRET=my-secret-key-12345
|
|
237
|
+
`);
|
|
238
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
239
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
240
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
241
|
+
expect(credFindings[0].severity).toBe('critical');
|
|
242
|
+
});
|
|
243
|
+
it('should detect NEXT_PUBLIC_API_KEY', async () => {
|
|
244
|
+
const file = await createTestFile('config.ts', `
|
|
245
|
+
const apiKey = process.env.NEXT_PUBLIC_API_KEY;
|
|
246
|
+
`);
|
|
247
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
248
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
249
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
250
|
+
});
|
|
251
|
+
it('should detect NEXT_PUBLIC_PASSWORD', async () => {
|
|
252
|
+
const file = await createTestFile('auth.ts', `
|
|
253
|
+
const password = process.env.NEXT_PUBLIC_PASSWORD;
|
|
254
|
+
`);
|
|
255
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
256
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
257
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
258
|
+
});
|
|
259
|
+
it('should detect NEXT_PUBLIC_SERVICE_ROLE', async () => {
|
|
260
|
+
const file = await createTestFile('supabase.ts', `
|
|
261
|
+
const serviceRole = process.env.NEXT_PUBLIC_SERVICE_ROLE;
|
|
262
|
+
`);
|
|
263
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
264
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
265
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
266
|
+
});
|
|
267
|
+
it('should detect NEXT_PUBLIC_PRIVATE_KEY', async () => {
|
|
268
|
+
const file = await createTestFile('crypto.ts', `
|
|
269
|
+
const privateKey = process.env.NEXT_PUBLIC_PRIVATE_KEY;
|
|
270
|
+
`);
|
|
271
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
272
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
273
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
274
|
+
});
|
|
275
|
+
it('should detect NEXT_PUBLIC_DATABASE_URL', async () => {
|
|
276
|
+
const file = await createTestFile('db.ts', `
|
|
277
|
+
const dbUrl = process.env.NEXT_PUBLIC_DATABASE_URL;
|
|
278
|
+
`);
|
|
279
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
280
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
281
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
282
|
+
});
|
|
283
|
+
it('should detect NEXT_PUBLIC_ADMIN_TOKEN', async () => {
|
|
284
|
+
const file = await createTestFile('admin.ts', `
|
|
285
|
+
const adminToken = process.env.NEXT_PUBLIC_ADMIN_TOKEN;
|
|
286
|
+
`);
|
|
287
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
288
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
289
|
+
expect(credFindings.length).toBeGreaterThan(0);
|
|
290
|
+
});
|
|
291
|
+
it('should not flag NEXT_PUBLIC_SUPABASE_ANON_KEY', async () => {
|
|
292
|
+
const file = await createTestFile('supabase-config.ts', `
|
|
293
|
+
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
|
294
|
+
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
|
|
295
|
+
`);
|
|
296
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
297
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
298
|
+
expect(credFindings.length).toBe(0);
|
|
299
|
+
});
|
|
300
|
+
it('should not flag NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY', async () => {
|
|
301
|
+
const file = await createTestFile('clerk.ts', `
|
|
302
|
+
const clerkKey = process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY;
|
|
303
|
+
`);
|
|
304
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
305
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
306
|
+
expect(credFindings.length).toBe(0);
|
|
307
|
+
});
|
|
308
|
+
it('should not flag NEXT_PUBLIC_GA_ID (Analytics)', async () => {
|
|
309
|
+
const file = await createTestFile('analytics.ts', `
|
|
310
|
+
const gaId = process.env.NEXT_PUBLIC_GA_ID;
|
|
311
|
+
`);
|
|
312
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
313
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
314
|
+
expect(credFindings.length).toBe(0);
|
|
315
|
+
});
|
|
316
|
+
it('should not flag NEXT_PUBLIC_APP_URL', async () => {
|
|
317
|
+
const file = await createTestFile('app-config.ts', `
|
|
318
|
+
const appUrl = process.env.NEXT_PUBLIC_APP_URL;
|
|
319
|
+
const siteName = process.env.NEXT_PUBLIC_SITE_NAME;
|
|
320
|
+
`);
|
|
321
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
322
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
323
|
+
expect(credFindings.length).toBe(0);
|
|
324
|
+
});
|
|
325
|
+
it('should not flag NEXT_PUBLIC_FEATURE_FLAG', async () => {
|
|
326
|
+
const file = await createTestFile('features.ts', `
|
|
327
|
+
const newFeature = process.env.NEXT_PUBLIC_FEATURE_NEW_UI;
|
|
328
|
+
`);
|
|
329
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
330
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-003');
|
|
331
|
+
expect(credFindings.length).toBe(0);
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
describe('General Scanner Behavior', () => {
|
|
335
|
+
it('should only scan code and config files', async () => {
|
|
336
|
+
await createTestFile('README.md', 'password = "secret123456"');
|
|
337
|
+
await createTestFile('image.png', 'binary data');
|
|
338
|
+
await createTestFile('code.ts', 'const password = "secret123456";');
|
|
339
|
+
const findings = await credentialsScanner.scan(testFiles, scanOptions);
|
|
340
|
+
const mdFindings = findings.filter((f) => f.file.endsWith('.md'));
|
|
341
|
+
const pngFindings = findings.filter((f) => f.file.endsWith('.png'));
|
|
342
|
+
expect(mdFindings.length).toBe(0);
|
|
343
|
+
expect(pngFindings.length).toBe(0);
|
|
344
|
+
});
|
|
345
|
+
it('should skip comment lines', async () => {
|
|
346
|
+
const file = await createTestFile('commented.ts', `
|
|
347
|
+
// const password = "hardcoded-secret";
|
|
348
|
+
/*
|
|
349
|
+
* const apiKey = "fake_key_1234567890";
|
|
350
|
+
*/
|
|
351
|
+
const validCode = true;
|
|
352
|
+
`);
|
|
353
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
354
|
+
const credFindings = findings.filter((f) => f.id === 'CRED-002');
|
|
355
|
+
expect(credFindings.length).toBe(0);
|
|
356
|
+
});
|
|
357
|
+
it('should include confidence scores', async () => {
|
|
358
|
+
const file = await createTestFile('test.ts', `
|
|
359
|
+
const password = "SecretPassword123!";
|
|
360
|
+
`);
|
|
361
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
362
|
+
for (const finding of findings) {
|
|
363
|
+
expect(finding.confidence).toBeDefined();
|
|
364
|
+
expect(['high', 'medium', 'low']).toContain(finding.confidence);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
it('should detect multiple violations in same file', async () => {
|
|
368
|
+
const file = await createTestFile('bad-security.ts', `
|
|
369
|
+
import crypto from 'crypto';
|
|
370
|
+
|
|
371
|
+
// CRED-001: Weak password hashing
|
|
372
|
+
function hashPassword(password: string) {
|
|
373
|
+
return crypto.createHash('md5').update(password).digest('hex');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// CRED-002: Hardcoded credentials
|
|
377
|
+
const config = {
|
|
378
|
+
apiKey: 'fake_key_ABCDEFGHIJKLMNOP1234567890',
|
|
379
|
+
password: 'AdminPassword123!'
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// CRED-003: Exposed secret
|
|
383
|
+
const secret = process.env.NEXT_PUBLIC_SECRET_KEY;
|
|
384
|
+
`);
|
|
385
|
+
const findings = await credentialsScanner.scan([file], scanOptions);
|
|
386
|
+
const cred001 = findings.filter((f) => f.id === 'CRED-001');
|
|
387
|
+
const cred002 = findings.filter((f) => f.id === 'CRED-002');
|
|
388
|
+
const cred003 = findings.filter((f) => f.id === 'CRED-003');
|
|
389
|
+
expect(cred001.length).toBeGreaterThan(0);
|
|
390
|
+
expect(cred002.length).toBeGreaterThan(0);
|
|
391
|
+
expect(cred003.length).toBeGreaterThan(0);
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/scanners/credentials/index.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential Security Detection Patterns
|
|
3
|
+
* Detects weak password hashing, hardcoded credentials, and exposed secrets
|
|
4
|
+
*/
|
|
5
|
+
export interface CredentialPattern {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
severity: 'critical' | 'high' | 'medium';
|
|
10
|
+
hipaaReference: string;
|
|
11
|
+
patterns: RegExp[];
|
|
12
|
+
negativePatterns?: RegExp[];
|
|
13
|
+
recommendation: string;
|
|
14
|
+
category: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* CRED-001: Weak Password Hashing Algorithm
|
|
18
|
+
* Detects MD5, SHA1, SHA256 for password hashing instead of bcrypt/argon2/scrypt
|
|
19
|
+
*/
|
|
20
|
+
export declare const WEAK_PASSWORD_HASH: CredentialPattern;
|
|
21
|
+
/**
|
|
22
|
+
* CRED-002: Hardcoded Credentials in Code
|
|
23
|
+
* Detects credentials assigned to string literals
|
|
24
|
+
*/
|
|
25
|
+
export declare const HARDCODED_CREDENTIALS: CredentialPattern;
|
|
26
|
+
/**
|
|
27
|
+
* CRED-003: Secrets Exposed via NEXT_PUBLIC_ Prefix
|
|
28
|
+
* Detects sensitive values exposed to client-side via Next.js public env vars
|
|
29
|
+
*/
|
|
30
|
+
export declare const NEXT_PUBLIC_SECRETS: CredentialPattern;
|
|
31
|
+
export declare const ALL_CREDENTIAL_PATTERNS: CredentialPattern[];
|
|
32
|
+
//# sourceMappingURL=patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../src/scanners/credentials/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,iBAqChC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,iBAuDnC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,iBAqDjC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,iBAAiB,EAItD,CAAC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential Security Detection Patterns
|
|
3
|
+
* Detects weak password hashing, hardcoded credentials, and exposed secrets
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* CRED-001: Weak Password Hashing Algorithm
|
|
7
|
+
* Detects MD5, SHA1, SHA256 for password hashing instead of bcrypt/argon2/scrypt
|
|
8
|
+
*/
|
|
9
|
+
export const WEAK_PASSWORD_HASH = {
|
|
10
|
+
id: 'CRED-001',
|
|
11
|
+
name: 'Weak Password Hashing Algorithm Detected',
|
|
12
|
+
description: 'Using MD5, SHA1, or SHA256 for password hashing instead of secure algorithms like bcrypt, argon2, or scrypt',
|
|
13
|
+
severity: 'critical',
|
|
14
|
+
hipaaReference: '45 CFR §164.312(d) - Person or Entity Authentication',
|
|
15
|
+
patterns: [
|
|
16
|
+
// crypto.createHash with weak algorithms near password
|
|
17
|
+
/createHash\s*\(\s*['"`](?:md5|sha1|sha-?1|sha256|sha-?256)['"`]\s*\)/i,
|
|
18
|
+
// hashlib with weak algorithms (Python)
|
|
19
|
+
/hashlib\.(?:md5|sha1|sha256)\s*\(/i,
|
|
20
|
+
// Direct mentions of weak hashing for passwords
|
|
21
|
+
/(?:md5|sha1|sha256).*?(?:password|pass|pwd|hash)/i,
|
|
22
|
+
/(?:password|pass|pwd).*?(?:md5|sha1|sha256)/i,
|
|
23
|
+
],
|
|
24
|
+
negativePatterns: [
|
|
25
|
+
// Secure algorithms
|
|
26
|
+
/bcrypt/i,
|
|
27
|
+
/argon2/i,
|
|
28
|
+
/scrypt/i,
|
|
29
|
+
/pbkdf2/i,
|
|
30
|
+
// Comments explaining not to use MD5
|
|
31
|
+
/\/\/.*(?:don't|do not|avoid|never).*md5/i,
|
|
32
|
+
/\/\*.*(?:don't|do not|avoid|never).*md5/i,
|
|
33
|
+
// Non-password use cases (checksums, file hashing)
|
|
34
|
+
/checksum/i,
|
|
35
|
+
/file.*hash/i,
|
|
36
|
+
/integrity/i,
|
|
37
|
+
],
|
|
38
|
+
recommendation: 'Use bcrypt, argon2, or scrypt for password hashing. Example: await bcrypt.hash(password, 10) or await argon2.hash(password). Never use MD5, SHA1, or simple SHA256 for passwords.',
|
|
39
|
+
category: 'encryption',
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* CRED-002: Hardcoded Credentials in Code
|
|
43
|
+
* Detects credentials assigned to string literals
|
|
44
|
+
*/
|
|
45
|
+
export const HARDCODED_CREDENTIALS = {
|
|
46
|
+
id: 'CRED-002',
|
|
47
|
+
name: 'Hardcoded Credentials Detected',
|
|
48
|
+
description: 'Credentials (password, apiKey, secret, token, connectionString) hardcoded as string literals instead of using environment variables',
|
|
49
|
+
severity: 'critical',
|
|
50
|
+
hipaaReference: '45 CFR §164.312(a)(2)(i) - Unique User Identification',
|
|
51
|
+
patterns: [
|
|
52
|
+
// Password assignments to string literals (8+ chars)
|
|
53
|
+
/(?:password|passwd|pwd)\s*[:=]\s*['"`][^'"`]{8,}['"`]/i,
|
|
54
|
+
// API keys
|
|
55
|
+
/(?:api[-_]?key|apikey)\s*[:=]\s*['"`][^'"`]{8,}['"`]/i,
|
|
56
|
+
// Secrets
|
|
57
|
+
/(?:secret|private[-_]?key|privatekey)\s*[:=]\s*['"`][^'"`]{8,}['"`]/i,
|
|
58
|
+
// Tokens
|
|
59
|
+
/(?:token|auth[-_]?token|access[-_]?token)\s*[:=]\s*['"`][^'"`]{16,}['"`]/i,
|
|
60
|
+
// Connection strings
|
|
61
|
+
/(?:connection[-_]?string|connectionstring|database[-_]?url)\s*[:=]\s*['"`][^'"`]{10,}['"`]/i,
|
|
62
|
+
// Bearer tokens
|
|
63
|
+
/['"`]Bearer\s+[A-Za-z0-9_\-\.]{16,}['"`]/i,
|
|
64
|
+
// AWS/Service keys
|
|
65
|
+
/(?:aws|service|client)[-_]?(?:key|secret)\s*[:=]\s*['"`][A-Za-z0-9+/]{20,}['"`]/i,
|
|
66
|
+
],
|
|
67
|
+
negativePatterns: [
|
|
68
|
+
// Environment variables
|
|
69
|
+
/process\.env/i,
|
|
70
|
+
/import\.meta\.env/i,
|
|
71
|
+
/env\./i,
|
|
72
|
+
/ENV\[/i,
|
|
73
|
+
/getenv/i,
|
|
74
|
+
// Placeholders
|
|
75
|
+
/your[-_]?(?:key|secret|password|token)/i,
|
|
76
|
+
/(?:placeholder|example|dummy|test|sample)/i,
|
|
77
|
+
/changeme/i,
|
|
78
|
+
/replace[-_]?(?:this|me)/i,
|
|
79
|
+
/(?:xxx|yyy|zzz)/i,
|
|
80
|
+
// Empty or template strings
|
|
81
|
+
/['"]\s*['"]/i,
|
|
82
|
+
/\$\{/i, // Template literals
|
|
83
|
+
// Comments
|
|
84
|
+
/\/\//i,
|
|
85
|
+
/\/\*/i,
|
|
86
|
+
],
|
|
87
|
+
recommendation: 'Move credentials to environment variables. Use process.env.PASSWORD or a secure secrets manager. Never commit credentials to source control. Add credentials to .gitignore.',
|
|
88
|
+
category: 'encryption',
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* CRED-003: Secrets Exposed via NEXT_PUBLIC_ Prefix
|
|
92
|
+
* Detects sensitive values exposed to client-side via Next.js public env vars
|
|
93
|
+
*/
|
|
94
|
+
export const NEXT_PUBLIC_SECRETS = {
|
|
95
|
+
id: 'CRED-003',
|
|
96
|
+
name: 'Secrets Exposed to Client via NEXT_PUBLIC_ Prefix',
|
|
97
|
+
description: 'Sensitive credentials exposed to client-side code using NEXT_PUBLIC_ environment variable prefix',
|
|
98
|
+
severity: 'critical',
|
|
99
|
+
hipaaReference: '45 CFR §164.312(a)(2)(i) - Unique User Identification',
|
|
100
|
+
patterns: [
|
|
101
|
+
// NEXT_PUBLIC_SECRET
|
|
102
|
+
/NEXT_PUBLIC_SECRET/i,
|
|
103
|
+
// NEXT_PUBLIC_*KEY
|
|
104
|
+
/NEXT_PUBLIC_.*?KEY/i,
|
|
105
|
+
// NEXT_PUBLIC_*PASSWORD
|
|
106
|
+
/NEXT_PUBLIC_.*?PASSWORD/i,
|
|
107
|
+
// NEXT_PUBLIC_SERVICE_ROLE
|
|
108
|
+
/NEXT_PUBLIC_SERVICE_ROLE/i,
|
|
109
|
+
// NEXT_PUBLIC_*TOKEN
|
|
110
|
+
/NEXT_PUBLIC_.*?TOKEN/i,
|
|
111
|
+
// NEXT_PUBLIC_*PRIVATE*
|
|
112
|
+
/NEXT_PUBLIC_.*?PRIVATE/i,
|
|
113
|
+
// NEXT_PUBLIC_DATABASE
|
|
114
|
+
/NEXT_PUBLIC_DATABASE/i,
|
|
115
|
+
// NEXT_PUBLIC_*ADMIN*
|
|
116
|
+
/NEXT_PUBLIC_.*?ADMIN/i,
|
|
117
|
+
],
|
|
118
|
+
negativePatterns: [
|
|
119
|
+
// Legitimate public keys
|
|
120
|
+
/NEXT_PUBLIC_(?:SUPABASE|FIREBASE|CLERK)_(?:ANON|PUBLISHABLE)_KEY/i,
|
|
121
|
+
/NEXT_PUBLIC_.*?PUBLISHABLE/i,
|
|
122
|
+
/NEXT_PUBLIC_.*?PUBLIC_KEY/i,
|
|
123
|
+
// Analytics and tracking (safe to expose)
|
|
124
|
+
/NEXT_PUBLIC_(?:GA|GTM|ANALYTICS|MIXPANEL|SEGMENT)_/i,
|
|
125
|
+
// App metadata (safe)
|
|
126
|
+
/NEXT_PUBLIC_(?:APP|SITE|BASE)_(?:URL|NAME|VERSION)/i,
|
|
127
|
+
// Feature flags
|
|
128
|
+
/NEXT_PUBLIC_FEATURE_/i,
|
|
129
|
+
// Comments explaining the issue
|
|
130
|
+
/\/\/.*(?:don't|do not|avoid|never)/i,
|
|
131
|
+
],
|
|
132
|
+
recommendation: 'Remove NEXT_PUBLIC_ prefix from sensitive variables. Use server-side environment variables (without NEXT_PUBLIC_) and access them in API routes or getServerSideProps. Only use NEXT_PUBLIC_ for truly public values like API endpoints or publishable keys.',
|
|
133
|
+
category: 'encryption',
|
|
134
|
+
};
|
|
135
|
+
export const ALL_CREDENTIAL_PATTERNS = [
|
|
136
|
+
WEAK_PASSWORD_HASH,
|
|
137
|
+
HARDCODED_CREDENTIALS,
|
|
138
|
+
NEXT_PUBLIC_SECRETS,
|
|
139
|
+
];
|
|
140
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/scanners/credentials/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsB;IACnD,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,0CAA0C;IAChD,WAAW,EACT,6GAA6G;IAC/G,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,sDAAsD;IACtE,QAAQ,EAAE;QACR,uDAAuD;QACvD,uEAAuE;QAEvE,wCAAwC;QACxC,oCAAoC;QAEpC,gDAAgD;QAChD,mDAAmD;QACnD,8CAA8C;KAC/C;IACD,gBAAgB,EAAE;QAChB,oBAAoB;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QAET,qCAAqC;QACrC,0CAA0C;QAC1C,0CAA0C;QAE1C,mDAAmD;QACnD,WAAW;QACX,aAAa;QACb,YAAY;KACb;IACD,cAAc,EACZ,mLAAmL;IACrL,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAsB;IACtD,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,gCAAgC;IACtC,WAAW,EACT,qIAAqI;IACvI,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,uDAAuD;IACvE,QAAQ,EAAE;QACR,qDAAqD;QACrD,wDAAwD;QAExD,WAAW;QACX,uDAAuD;QAEvD,UAAU;QACV,sEAAsE;QAEtE,SAAS;QACT,2EAA2E;QAE3E,qBAAqB;QACrB,6FAA6F;QAE7F,gBAAgB;QAChB,2CAA2C;QAE3C,mBAAmB;QACnB,kFAAkF;KACnF;IACD,gBAAgB,EAAE;QAChB,wBAAwB;QACxB,eAAe;QACf,oBAAoB;QACpB,QAAQ;QACR,QAAQ;QACR,SAAS;QAET,eAAe;QACf,yCAAyC;QACzC,4CAA4C;QAC5C,WAAW;QACX,0BAA0B;QAC1B,kBAAkB;QAElB,4BAA4B;QAC5B,cAAc;QACd,OAAO,EAAE,oBAAoB;QAE7B,WAAW;QACX,OAAO;QACP,OAAO;KACR;IACD,cAAc,EACZ,6KAA6K;IAC/K,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAsB;IACpD,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,mDAAmD;IACzD,WAAW,EACT,kGAAkG;IACpG,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,uDAAuD;IACvE,QAAQ,EAAE;QACR,qBAAqB;QACrB,qBAAqB;QAErB,mBAAmB;QACnB,qBAAqB;QAErB,wBAAwB;QACxB,0BAA0B;QAE1B,2BAA2B;QAC3B,2BAA2B;QAE3B,qBAAqB;QACrB,uBAAuB;QAEvB,wBAAwB;QACxB,yBAAyB;QAEzB,uBAAuB;QACvB,uBAAuB;QAEvB,sBAAsB;QACtB,uBAAuB;KACxB;IACD,gBAAgB,EAAE;QAChB,yBAAyB;QACzB,mEAAmE;QACnE,6BAA6B;QAC7B,4BAA4B;QAE5B,0CAA0C;QAC1C,qDAAqD;QAErD,sBAAsB;QACtB,qDAAqD;QAErD,gBAAgB;QAChB,uBAAuB;QAEvB,gCAAgC;QAChC,qCAAqC;KACtC;IACD,cAAc,EACZ,8PAA8P;IAChQ,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAwB;IAC1D,kBAAkB;IAClB,qBAAqB;IACrB,mBAAmB;CACpB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Handling Security Scanner
|
|
3
|
+
* Detects unsafe error responses and PHI in error logs
|
|
4
|
+
*/
|
|
5
|
+
import type { Scanner } from '../../types.js';
|
|
6
|
+
export declare const errorsScanner: Scanner;
|
|
7
|
+
export default errorsScanner;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/errors/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAwB,MAAM,gBAAgB,CAAC;AAGpE,eAAO,MAAM,aAAa,EAAE,OAqF3B,CAAC;AAEF,eAAe,aAAa,CAAC"}
|