verification-layer 0.21.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.
Files changed (157) hide show
  1. package/README.md +251 -615
  2. package/dist/cli.js +283 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/reporters/audit-report.d.ts.map +1 -1
  5. package/dist/reporters/audit-report.js +180 -0
  6. package/dist/reporters/audit-report.js.map +1 -1
  7. package/dist/reporters/index.d.ts.map +1 -1
  8. package/dist/reporters/index.js +2612 -5
  9. package/dist/reporters/index.js.map +1 -1
  10. package/dist/scan.d.ts.map +1 -1
  11. package/dist/scan.js +14 -1
  12. package/dist/scan.js.map +1 -1
  13. package/dist/scanners/api-security/index.d.ts +7 -0
  14. package/dist/scanners/api-security/index.d.ts.map +1 -0
  15. package/dist/scanners/api-security/index.js +139 -0
  16. package/dist/scanners/api-security/index.js.map +1 -0
  17. package/dist/scanners/api-security/index.test.d.ts +5 -0
  18. package/dist/scanners/api-security/index.test.d.ts.map +1 -0
  19. package/dist/scanners/api-security/index.test.js +360 -0
  20. package/dist/scanners/api-security/index.test.js.map +1 -0
  21. package/dist/scanners/api-security/patterns.d.ts +32 -0
  22. package/dist/scanners/api-security/patterns.d.ts.map +1 -0
  23. package/dist/scanners/api-security/patterns.js +159 -0
  24. package/dist/scanners/api-security/patterns.js.map +1 -0
  25. package/dist/scanners/authentication/index.d.ts +7 -0
  26. package/dist/scanners/authentication/index.d.ts.map +1 -0
  27. package/dist/scanners/authentication/index.js +107 -0
  28. package/dist/scanners/authentication/index.js.map +1 -0
  29. package/dist/scanners/authentication/index.test.d.ts +5 -0
  30. package/dist/scanners/authentication/index.test.d.ts.map +1 -0
  31. package/dist/scanners/authentication/index.test.js +379 -0
  32. package/dist/scanners/authentication/index.test.js.map +1 -0
  33. package/dist/scanners/authentication/patterns.d.ts +32 -0
  34. package/dist/scanners/authentication/patterns.d.ts.map +1 -0
  35. package/dist/scanners/authentication/patterns.js +133 -0
  36. package/dist/scanners/authentication/patterns.js.map +1 -0
  37. package/dist/scanners/configuration/index.d.ts +8 -0
  38. package/dist/scanners/configuration/index.d.ts.map +1 -0
  39. package/dist/scanners/configuration/index.js +87 -0
  40. package/dist/scanners/configuration/index.js.map +1 -0
  41. package/dist/scanners/configuration/index.test.d.ts +5 -0
  42. package/dist/scanners/configuration/index.test.d.ts.map +1 -0
  43. package/dist/scanners/configuration/index.test.js +344 -0
  44. package/dist/scanners/configuration/index.test.js.map +1 -0
  45. package/dist/scanners/configuration/patterns.d.ts +32 -0
  46. package/dist/scanners/configuration/patterns.d.ts.map +1 -0
  47. package/dist/scanners/configuration/patterns.js +146 -0
  48. package/dist/scanners/configuration/patterns.js.map +1 -0
  49. package/dist/scanners/credentials/index.d.ts +7 -0
  50. package/dist/scanners/credentials/index.d.ts.map +1 -0
  51. package/dist/scanners/credentials/index.js +129 -0
  52. package/dist/scanners/credentials/index.js.map +1 -0
  53. package/dist/scanners/credentials/index.test.d.ts +5 -0
  54. package/dist/scanners/credentials/index.test.d.ts.map +1 -0
  55. package/dist/scanners/credentials/index.test.js +395 -0
  56. package/dist/scanners/credentials/index.test.js.map +1 -0
  57. package/dist/scanners/credentials/patterns.d.ts +32 -0
  58. package/dist/scanners/credentials/patterns.d.ts.map +1 -0
  59. package/dist/scanners/credentials/patterns.js +140 -0
  60. package/dist/scanners/credentials/patterns.js.map +1 -0
  61. package/dist/scanners/errors/index.d.ts +8 -0
  62. package/dist/scanners/errors/index.d.ts.map +1 -0
  63. package/dist/scanners/errors/index.js +78 -0
  64. package/dist/scanners/errors/index.js.map +1 -0
  65. package/dist/scanners/errors/index.test.d.ts +5 -0
  66. package/dist/scanners/errors/index.test.d.ts.map +1 -0
  67. package/dist/scanners/errors/index.test.js +330 -0
  68. package/dist/scanners/errors/index.test.js.map +1 -0
  69. package/dist/scanners/errors/patterns.d.ts +27 -0
  70. package/dist/scanners/errors/patterns.d.ts.map +1 -0
  71. package/dist/scanners/errors/patterns.js +97 -0
  72. package/dist/scanners/errors/patterns.js.map +1 -0
  73. package/dist/scanners/hipaa2026/index.d.ts.map +1 -1
  74. package/dist/scanners/hipaa2026/index.js +49 -17
  75. package/dist/scanners/hipaa2026/index.js.map +1 -1
  76. package/dist/scanners/hipaa2026/index.test.js +26 -15
  77. package/dist/scanners/hipaa2026/index.test.js.map +1 -1
  78. package/dist/scanners/operational/index.d.ts +7 -0
  79. package/dist/scanners/operational/index.d.ts.map +1 -0
  80. package/dist/scanners/operational/index.js +171 -0
  81. package/dist/scanners/operational/index.js.map +1 -0
  82. package/dist/scanners/operational/index.test.d.ts +5 -0
  83. package/dist/scanners/operational/index.test.d.ts.map +1 -0
  84. package/dist/scanners/operational/index.test.js +406 -0
  85. package/dist/scanners/operational/index.test.js.map +1 -0
  86. package/dist/scanners/operational/patterns.d.ts +33 -0
  87. package/dist/scanners/operational/patterns.d.ts.map +1 -0
  88. package/dist/scanners/operational/patterns.js +151 -0
  89. package/dist/scanners/operational/patterns.js.map +1 -0
  90. package/dist/scanners/rbac/index.d.ts +7 -0
  91. package/dist/scanners/rbac/index.d.ts.map +1 -0
  92. package/dist/scanners/rbac/index.js +145 -0
  93. package/dist/scanners/rbac/index.js.map +1 -0
  94. package/dist/scanners/rbac/index.test.d.ts +5 -0
  95. package/dist/scanners/rbac/index.test.d.ts.map +1 -0
  96. package/dist/scanners/rbac/index.test.js +422 -0
  97. package/dist/scanners/rbac/index.test.js.map +1 -0
  98. package/dist/scanners/rbac/patterns.d.ts +32 -0
  99. package/dist/scanners/rbac/patterns.d.ts.map +1 -0
  100. package/dist/scanners/rbac/patterns.js +124 -0
  101. package/dist/scanners/rbac/patterns.js.map +1 -0
  102. package/dist/scanners/revocation/index.d.ts +8 -0
  103. package/dist/scanners/revocation/index.d.ts.map +1 -0
  104. package/dist/scanners/revocation/index.js +83 -0
  105. package/dist/scanners/revocation/index.js.map +1 -0
  106. package/dist/scanners/revocation/index.test.d.ts +5 -0
  107. package/dist/scanners/revocation/index.test.d.ts.map +1 -0
  108. package/dist/scanners/revocation/index.test.js +332 -0
  109. package/dist/scanners/revocation/index.test.js.map +1 -0
  110. package/dist/scanners/revocation/patterns.d.ts +27 -0
  111. package/dist/scanners/revocation/patterns.d.ts.map +1 -0
  112. package/dist/scanners/revocation/patterns.js +109 -0
  113. package/dist/scanners/revocation/patterns.js.map +1 -0
  114. package/dist/scanners/sanitization/index.d.ts +8 -0
  115. package/dist/scanners/sanitization/index.d.ts.map +1 -0
  116. package/dist/scanners/sanitization/index.js +98 -0
  117. package/dist/scanners/sanitization/index.js.map +1 -0
  118. package/dist/scanners/sanitization/index.test.d.ts +5 -0
  119. package/dist/scanners/sanitization/index.test.d.ts.map +1 -0
  120. package/dist/scanners/sanitization/index.test.js +370 -0
  121. package/dist/scanners/sanitization/index.test.js.map +1 -0
  122. package/dist/scanners/sanitization/patterns.d.ts +27 -0
  123. package/dist/scanners/sanitization/patterns.d.ts.map +1 -0
  124. package/dist/scanners/sanitization/patterns.js +117 -0
  125. package/dist/scanners/sanitization/patterns.js.map +1 -0
  126. package/dist/training/certificate.d.ts +26 -0
  127. package/dist/training/certificate.d.ts.map +1 -0
  128. package/dist/training/certificate.js +92 -0
  129. package/dist/training/certificate.js.map +1 -0
  130. package/dist/training/index.d.ts +3 -0
  131. package/dist/training/index.d.ts.map +1 -0
  132. package/dist/training/index.js +243 -0
  133. package/dist/training/index.js.map +1 -0
  134. package/dist/training/modules.d.ts +13 -0
  135. package/dist/training/modules.d.ts.map +1 -0
  136. package/dist/training/modules.js +608 -0
  137. package/dist/training/modules.js.map +1 -0
  138. package/dist/training/questions.d.ts +9 -0
  139. package/dist/training/questions.d.ts.map +1 -0
  140. package/dist/training/questions.js +505 -0
  141. package/dist/training/questions.js.map +1 -0
  142. package/dist/types.d.ts +45 -0
  143. package/dist/types.d.ts.map +1 -1
  144. package/dist/utils/npm-audit.d.ts +6 -0
  145. package/dist/utils/npm-audit.d.ts.map +1 -0
  146. package/dist/utils/npm-audit.js +95 -0
  147. package/dist/utils/npm-audit.js.map +1 -0
  148. package/dist/utils/scan-history.d.ts +59 -0
  149. package/dist/utils/scan-history.d.ts.map +1 -0
  150. package/dist/utils/scan-history.js +170 -0
  151. package/dist/utils/scan-history.js.map +1 -0
  152. package/package.json +4 -1
  153. package/templates/baa-verification-letter.md +105 -0
  154. package/templates/irp.md +545 -0
  155. package/templates/notice-of-privacy-practices.md +491 -0
  156. package/templates/physical-safeguards-checklist.md +247 -0
  157. package/templates/security-officer-designation.md +237 -0
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Multi-Factor Authentication (MFA) Scanner
3
+ * Detects missing or bypassed MFA in authentication flows
4
+ */
5
+ import * as fs from 'fs/promises';
6
+ import { ALL_MFA_PATTERNS } from './patterns.js';
7
+ export const authenticationScanner = {
8
+ name: 'Multi-Factor Authentication Scanner',
9
+ category: 'access-control', // Map to existing category for now
10
+ async scan(files, options) {
11
+ const findings = [];
12
+ // Filter to code and config files
13
+ const relevantFiles = files.filter((f) => /\.(js|ts|jsx|tsx|json|yaml|yml|env)$/i.test(f));
14
+ // Common auth config file patterns
15
+ const authConfigFiles = relevantFiles.filter((f) => /(?:auth|clerk|supabase|next-auth).*\.(?:ts|js|json|config)/i.test(f));
16
+ for (const file of relevantFiles) {
17
+ try {
18
+ const content = await fs.readFile(file, 'utf-8');
19
+ const lines = content.split('\n');
20
+ for (const pattern of ALL_MFA_PATTERNS) {
21
+ // Special handling for MFA-001 (auth config files)
22
+ if (pattern.id === 'MFA-001') {
23
+ await scanAuthConfig(file, content, lines, pattern, findings);
24
+ continue;
25
+ }
26
+ // Standard pattern matching for MFA-002 and MFA-003
27
+ for (let i = 0; i < lines.length; i++) {
28
+ const line = lines[i];
29
+ const lineNumber = i + 1;
30
+ // Skip comments
31
+ if (/^\s*(?:\/\/|#|\*)/.test(line))
32
+ continue;
33
+ // Check if line matches violation pattern
34
+ const matched = pattern.patterns.some((p) => p.test(line));
35
+ if (!matched)
36
+ continue;
37
+ // Check if negative patterns indicate compliance
38
+ const isCompliant = pattern.negativePatterns?.some((p) => {
39
+ // Check current line and next 5 lines for compliance indicators
40
+ const context = lines.slice(i, i + 6).join('\n');
41
+ return p.test(context);
42
+ });
43
+ if (isCompliant)
44
+ continue;
45
+ // Create finding
46
+ findings.push({
47
+ id: pattern.id,
48
+ category: 'access-control',
49
+ severity: pattern.severity,
50
+ title: pattern.name,
51
+ description: `${pattern.description}\n\nCode: ${line.trim()}`,
52
+ file: file,
53
+ line: lineNumber,
54
+ recommendation: pattern.recommendation,
55
+ hipaaReference: pattern.hipaaReference,
56
+ confidence: 'high',
57
+ });
58
+ }
59
+ }
60
+ }
61
+ catch (error) {
62
+ // Skip files that can't be read
63
+ }
64
+ }
65
+ return findings;
66
+ },
67
+ };
68
+ /**
69
+ * Scan auth configuration files for missing MFA
70
+ */
71
+ async function scanAuthConfig(file, content, lines, pattern, findings) {
72
+ // Check if this is an auth-related file
73
+ const isAuthFile = /(?:auth|clerk|supabase|next-auth)/i.test(file) ||
74
+ pattern.patterns.some((p) => p.test(content));
75
+ if (!isAuthFile)
76
+ return;
77
+ // Check if file has any auth provider configuration
78
+ const hasAuthConfig = pattern.patterns.some((p) => p.test(content));
79
+ if (!hasAuthConfig)
80
+ return;
81
+ // Check if MFA is configured
82
+ const hasMfaConfig = pattern.negativePatterns?.some((p) => p.test(content));
83
+ if (hasMfaConfig)
84
+ return;
85
+ // Find the line with auth configuration
86
+ let configLine = 1;
87
+ for (let i = 0; i < lines.length; i++) {
88
+ if (pattern.patterns.some((p) => p.test(lines[i]))) {
89
+ configLine = i + 1;
90
+ break;
91
+ }
92
+ }
93
+ // Create finding for auth config without MFA
94
+ findings.push({
95
+ id: pattern.id,
96
+ category: 'access-control',
97
+ severity: pattern.severity,
98
+ title: pattern.name,
99
+ description: `${pattern.description}\n\nFile contains auth configuration but no MFA setup detected.`,
100
+ file: file,
101
+ line: configLine,
102
+ recommendation: pattern.recommendation,
103
+ hipaaReference: pattern.hipaaReference,
104
+ confidence: 'high',
105
+ });
106
+ }
107
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/authentication/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for Multi-Factor Authentication Scanner
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/scanners/authentication/index.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Tests for Multi-Factor Authentication Scanner
3
+ */
4
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
+ import { authenticationScanner } from './index.js';
6
+ import * as fs from 'fs/promises';
7
+ import * as path from 'path';
8
+ import * as os from 'os';
9
+ describe('Authentication Scanner', () => {
10
+ let tempDir = '';
11
+ let testFiles = [];
12
+ beforeEach(async () => {
13
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'auth-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('MFA-001: Auth Configuration Without MFA', () => {
43
+ it('should detect NextAuth without MFA', async () => {
44
+ const file = await createTestFile('auth.ts', `
45
+ import NextAuth from 'next-auth';
46
+ import CredentialsProvider from 'next-auth/providers/credentials';
47
+
48
+ export default NextAuth({
49
+ providers: [
50
+ CredentialsProvider({
51
+ credentials: {
52
+ email: { label: "Email", type: "email" },
53
+ password: { label: "Password", type: "password" }
54
+ },
55
+ async authorize(credentials) {
56
+ const user = await verifyCredentials(credentials);
57
+ return user;
58
+ }
59
+ })
60
+ ],
61
+ session: {
62
+ strategy: 'jwt'
63
+ }
64
+ });
65
+ `);
66
+ const findings = await authenticationScanner.scan([file], scanOptions);
67
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-001');
68
+ expect(mfaFindings.length).toBeGreaterThan(0);
69
+ expect(mfaFindings[0].severity).toBe('critical');
70
+ expect(mfaFindings[0].hipaaReference).toContain('164.312(d)');
71
+ });
72
+ it('should not flag NextAuth with MFA enabled', async () => {
73
+ const file = await createTestFile('auth-secure.ts', `
74
+ import NextAuth from 'next-auth';
75
+ import CredentialsProvider from 'next-auth/providers/credentials';
76
+
77
+ export default NextAuth({
78
+ providers: [
79
+ CredentialsProvider({
80
+ credentials: {
81
+ email: { label: "Email", type: "email" },
82
+ password: { label: "Password", type: "password" },
83
+ totpCode: { label: "TOTP Code", type: "text" }
84
+ },
85
+ async authorize(credentials) {
86
+ const user = await verifyCredentials(credentials);
87
+ // Verify MFA
88
+ if (user.mfaEnabled) {
89
+ const validTotp = await verifyTotp(user.id, credentials.totpCode);
90
+ if (!validTotp) return null;
91
+ }
92
+ return user;
93
+ }
94
+ })
95
+ ],
96
+ session: {
97
+ strategy: 'jwt'
98
+ }
99
+ });
100
+ `);
101
+ const findings = await authenticationScanner.scan([file], scanOptions);
102
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-001');
103
+ expect(mfaFindings.length).toBe(0);
104
+ });
105
+ it('should detect Clerk configuration without MFA', async () => {
106
+ const file = await createTestFile('clerk-provider.tsx', `
107
+ import { ClerkProvider } from '@clerk/nextjs';
108
+
109
+ export default function RootLayout({ children }) {
110
+ return (
111
+ <ClerkProvider
112
+ appearance={{
113
+ variables: { colorPrimary: '#000' }
114
+ }}
115
+ >
116
+ {children}
117
+ </ClerkProvider>
118
+ );
119
+ }
120
+ `);
121
+ const findings = await authenticationScanner.scan([file], scanOptions);
122
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-001');
123
+ expect(mfaFindings.length).toBeGreaterThan(0);
124
+ expect(mfaFindings[0].severity).toBe('critical');
125
+ });
126
+ it('should detect Auth0 configuration without MFA', async () => {
127
+ const file = await createTestFile('auth0-config.ts', `
128
+ import { Auth0Provider } from '@auth0/auth0-react';
129
+
130
+ const Auth0Config = () => (
131
+ <Auth0Provider
132
+ domain="myapp.auth0.com"
133
+ clientId="abc123"
134
+ redirectUri={window.location.origin}
135
+ >
136
+ <App />
137
+ </Auth0Provider>
138
+ );
139
+ `);
140
+ const findings = await authenticationScanner.scan([file], scanOptions);
141
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-001');
142
+ expect(mfaFindings.length).toBeGreaterThan(0);
143
+ });
144
+ it('should detect Supabase Auth without MFA', async () => {
145
+ const file = await createTestFile('supabase-config.ts', `
146
+ import { createClient } from '@supabase/supabase-js';
147
+
148
+ const supabase = createClient(
149
+ 'https://myproject.supabase.co',
150
+ 'public-anon-key'
151
+ );
152
+
153
+ export async function signUp(email: string, password: string) {
154
+ const { data, error } = await supabase.auth.signUp({
155
+ email,
156
+ password,
157
+ });
158
+ return { data, error };
159
+ }
160
+ `);
161
+ const findings = await authenticationScanner.scan([file], scanOptions);
162
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-001');
163
+ expect(mfaFindings.length).toBeGreaterThan(0);
164
+ });
165
+ });
166
+ describe('MFA-002: Login Flow Without Second Factor', () => {
167
+ it('should detect signIn with only email+password', async () => {
168
+ const file = await createTestFile('login.ts', `
169
+ export async function handleLogin(email: string, password: string) {
170
+ const result = await signIn('credentials', {
171
+ email,
172
+ password,
173
+ redirect: false,
174
+ });
175
+
176
+ if (result?.ok) {
177
+ router.push('/dashboard');
178
+ }
179
+ }
180
+ `);
181
+ const findings = await authenticationScanner.scan([file], scanOptions);
182
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-002');
183
+ expect(mfaFindings.length).toBeGreaterThan(0);
184
+ expect(mfaFindings[0].severity).toBe('high');
185
+ });
186
+ it('should detect login with credentials object', async () => {
187
+ const file = await createTestFile('auth-handler.ts', `
188
+ async function authenticate(credentials: { email: string; password: string }) {
189
+ const user = await login(credentials);
190
+ return user;
191
+ }
192
+ `);
193
+ const findings = await authenticationScanner.scan([file], scanOptions);
194
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-002');
195
+ expect(mfaFindings.length).toBeGreaterThan(0);
196
+ });
197
+ it('should not flag login with MFA verification', async () => {
198
+ const file = await createTestFile('login-secure.ts', `
199
+ export async function handleLogin(
200
+ email: string,
201
+ password: string,
202
+ mfaToken: string
203
+ ) {
204
+ const result = await signIn('credentials', {
205
+ email,
206
+ password,
207
+ mfaToken,
208
+ redirect: false,
209
+ });
210
+
211
+ if (result?.ok) {
212
+ router.push('/dashboard');
213
+ }
214
+ }
215
+ `);
216
+ const findings = await authenticationScanner.scan([file], scanOptions);
217
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-002');
218
+ expect(mfaFindings.length).toBe(0);
219
+ });
220
+ it('should not flag login with TOTP code', async () => {
221
+ const file = await createTestFile('login-totp.ts', `
222
+ async function authenticate(email: string, password: string, totpCode: string) {
223
+ const user = await verifyPassword(email, password);
224
+ if (!user) return null;
225
+
226
+ const validTotp = await verifyTotpCode(user.id, totpCode);
227
+ if (!validTotp) return null;
228
+
229
+ return user;
230
+ }
231
+ `);
232
+ const findings = await authenticationScanner.scan([file], scanOptions);
233
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-002');
234
+ expect(mfaFindings.length).toBe(0);
235
+ });
236
+ });
237
+ describe('MFA-003: MFA Bypass Detected', () => {
238
+ it('should detect skipMfa function call', async () => {
239
+ const file = await createTestFile('bypass.ts', `
240
+ async function login(user: User) {
241
+ if (process.env.NODE_ENV === 'development') {
242
+ return skipMfa(user);
243
+ }
244
+ return requireMfaVerification(user);
245
+ }
246
+ `);
247
+ const findings = await authenticationScanner.scan([file], scanOptions);
248
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-003');
249
+ expect(mfaFindings.length).toBeGreaterThan(0);
250
+ expect(mfaFindings[0].severity).toBe('critical');
251
+ });
252
+ it('should detect bypassMfa in code', async () => {
253
+ const file = await createTestFile('bypass-func.ts', `
254
+ function authenticate(user: User, bypassMfa = false) {
255
+ if (bypassMfa) {
256
+ return grantAccess(user);
257
+ }
258
+ return checkMfaAndGrant(user);
259
+ }
260
+ `);
261
+ const findings = await authenticationScanner.scan([file], scanOptions);
262
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-003');
263
+ expect(mfaFindings.length).toBeGreaterThan(0);
264
+ });
265
+ it('should detect mfaEnabled=false', async () => {
266
+ const file = await createTestFile('config-bypass.ts', `
267
+ const authConfig = {
268
+ providers: ['google', 'github'],
269
+ mfaEnabled: false,
270
+ sessionTimeout: 3600
271
+ };
272
+ `);
273
+ const findings = await authenticationScanner.scan([file], scanOptions);
274
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-003');
275
+ expect(mfaFindings.length).toBeGreaterThan(0);
276
+ });
277
+ it('should detect requireMfa=false', async () => {
278
+ const file = await createTestFile('mfa-disabled.ts', `
279
+ export const authOptions = {
280
+ requireMfa: false,
281
+ allowPasswordReset: true
282
+ };
283
+ `);
284
+ const findings = await authenticationScanner.scan([file], scanOptions);
285
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-003');
286
+ expect(mfaFindings.length).toBeGreaterThan(0);
287
+ });
288
+ it('should detect environment-based MFA bypass', async () => {
289
+ const file = await createTestFile('env-bypass.ts', `
290
+ const mfaRequired = !process.env.SKIP_MFA;
291
+
292
+ if (process.env.DISABLE_MFA === 'true') {
293
+ console.log('MFA disabled');
294
+ }
295
+ `);
296
+ const findings = await authenticationScanner.scan([file], scanOptions);
297
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-003');
298
+ expect(mfaFindings.length).toBeGreaterThan(0);
299
+ });
300
+ it('should not flag MFA bypass in test files', async () => {
301
+ const file = await createTestFile('auth.test.ts', `
302
+ describe('Auth', () => {
303
+ it('should allow skipMfa in tests', () => {
304
+ const user = skipMfa(testUser);
305
+ expect(user).toBeDefined();
306
+ });
307
+ });
308
+ `);
309
+ const findings = await authenticationScanner.scan([file], scanOptions);
310
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-003');
311
+ expect(mfaFindings.length).toBe(0);
312
+ });
313
+ it('should not flag MFA bypass in error messages', async () => {
314
+ const file = await createTestFile('error-handler.ts', `
315
+ function validateMfa(user: User) {
316
+ if (!user.mfaEnabled) {
317
+ throw new Error('MFA is disabled for this user. Please contact admin.');
318
+ }
319
+ console.warn('User has mfaEnabled: false in profile');
320
+ }
321
+ `);
322
+ const findings = await authenticationScanner.scan([file], scanOptions);
323
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-003');
324
+ expect(mfaFindings.length).toBe(0);
325
+ });
326
+ });
327
+ describe('General Scanner Behavior', () => {
328
+ it('should only scan relevant file types', async () => {
329
+ await createTestFile('README.md', 'signIn(email, password)');
330
+ await createTestFile('data.json', '{"mfaEnabled": false}');
331
+ await createTestFile('code.ts', 'const user = signIn(email, password);');
332
+ const findings = await authenticationScanner.scan(testFiles, scanOptions);
333
+ // Should only find findings in .ts file
334
+ const mdFindings = findings.filter((f) => f.file.endsWith('.md'));
335
+ expect(mdFindings.length).toBe(0);
336
+ });
337
+ it('should skip comment lines', async () => {
338
+ const file = await createTestFile('commented.ts', `
339
+ // This is how to skipMfa (don't do this!)
340
+ /*
341
+ * bypassMfa should never be used
342
+ */
343
+ const validCode = true;
344
+ `);
345
+ const findings = await authenticationScanner.scan([file], scanOptions);
346
+ const mfaFindings = findings.filter((f) => f.id === 'MFA-003');
347
+ expect(mfaFindings.length).toBe(0);
348
+ });
349
+ it('should include confidence scores', async () => {
350
+ const file = await createTestFile('test.ts', `
351
+ const config = {
352
+ mfaEnabled: false
353
+ };
354
+ `);
355
+ const findings = await authenticationScanner.scan([file], scanOptions);
356
+ for (const finding of findings) {
357
+ expect(finding.confidence).toBeDefined();
358
+ expect(['high', 'medium', 'low']).toContain(finding.confidence);
359
+ }
360
+ });
361
+ it('should include proper HIPAA references', async () => {
362
+ const file = await createTestFile('auth.ts', `
363
+ export default NextAuth({
364
+ providers: [
365
+ CredentialsProvider({
366
+ credentials: { email: {}, password: {} }
367
+ })
368
+ ]
369
+ });
370
+ `);
371
+ const findings = await authenticationScanner.scan([file], scanOptions);
372
+ for (const finding of findings) {
373
+ expect(finding.hipaaReference).toBeDefined();
374
+ expect(finding.hipaaReference).toContain('164.312(d)');
375
+ }
376
+ });
377
+ });
378
+ });
379
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/scanners/authentication/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Multi-Factor Authentication (MFA) Detection Patterns
3
+ * Enforces MFA requirements per HIPAA NPRM §164.312(d)
4
+ */
5
+ export interface MFAPattern {
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
+ * MFA-001: Auth Provider Configuration Without MFA
18
+ * Detects NextAuth, Clerk, Auth0, Supabase Auth configs without MFA enabled
19
+ */
20
+ export declare const AUTH_CONFIG_NO_MFA: MFAPattern;
21
+ /**
22
+ * MFA-002: Login Flow Without Second Factor
23
+ * Detects signIn/login with only email+password without MFA verification
24
+ */
25
+ export declare const LOGIN_NO_SECOND_FACTOR: MFAPattern;
26
+ /**
27
+ * MFA-003: MFA Bypass in Code
28
+ * Detects code that explicitly bypasses or disables MFA requirements
29
+ */
30
+ export declare const MFA_BYPASS: MFAPattern;
31
+ export declare const ALL_MFA_PATTERNS: MFAPattern[];
32
+ //# sourceMappingURL=patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../src/scanners/authentication/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,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,UA6ChC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,UAmCpC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,UA2CxB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,UAAU,EAIxC,CAAC"}