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,360 @@
1
+ /**
2
+ * API Security Scanner Tests
3
+ */
4
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
+ import { apiSecurityScanner } from './index.js';
6
+ import * as fs from 'fs/promises';
7
+ import * as path from 'path';
8
+ import * as os from 'os';
9
+ describe('API Security Scanner', () => {
10
+ let tempDir = '';
11
+ let testFiles = [];
12
+ beforeEach(async () => {
13
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'api-security-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('RATE-001: Authentication Routes Without Rate Limiting', () => {
43
+ it('should detect POST /login without rate limiting', async () => {
44
+ const file = await createTestFile('auth.ts', `
45
+ import express from 'express';
46
+
47
+ const app = express();
48
+
49
+ app.post('/login', (req, res) => {
50
+ // Login logic
51
+ res.json({ success: true });
52
+ });
53
+ `);
54
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
55
+ const rateFindings = findings.filter((f) => f.id === 'RATE-001');
56
+ expect(rateFindings.length).toBeGreaterThan(0);
57
+ expect(rateFindings[0].severity).toBe('high');
58
+ });
59
+ it('should detect POST /api/auth without rate limiting', async () => {
60
+ const file = await createTestFile('api-auth.ts', `
61
+ router.post('/api/auth', authHandler);
62
+ `);
63
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
64
+ expect(findings.some((f) => f.id === 'RATE-001')).toBe(true);
65
+ });
66
+ it('should detect POST /register without rate limiting', async () => {
67
+ const file = await createTestFile('register.ts', `
68
+ app.post('/register', async (req, res) => {
69
+ const user = await createUser(req.body);
70
+ res.json(user);
71
+ });
72
+ `);
73
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
74
+ expect(findings.some((f) => f.id === 'RATE-001')).toBe(true);
75
+ });
76
+ it('should detect POST /password-reset without rate limiting', async () => {
77
+ const file = await createTestFile('reset.ts', `
78
+ app.post('/password-reset', passwordResetHandler);
79
+ `);
80
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
81
+ expect(findings.some((f) => f.id === 'RATE-001')).toBe(true);
82
+ });
83
+ it('should detect Fastify auth route without rate limiting', async () => {
84
+ const file = await createTestFile('fastify-auth.ts', `
85
+ fastify.post('/login', async (request, reply) => {
86
+ return { token: 'abc' };
87
+ });
88
+ `);
89
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
90
+ expect(findings.some((f) => f.id === 'RATE-001')).toBe(true);
91
+ });
92
+ it('should detect Hono auth route without rate limiting', async () => {
93
+ const file = await createTestFile('hono-auth.ts', `
94
+ import { Hono } from 'hono';
95
+ const app = new Hono();
96
+
97
+ app.post('/signin', (c) => {
98
+ return c.json({ token: 'abc' });
99
+ });
100
+ `);
101
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
102
+ expect(findings.some((f) => f.id === 'RATE-001')).toBe(true);
103
+ });
104
+ it('should NOT flag auth route with rateLimit middleware', async () => {
105
+ const file = await createTestFile('safe-login.ts', `
106
+ import rateLimit from 'express-rate-limit';
107
+
108
+ const loginLimiter = rateLimit({
109
+ windowMs: 15 * 60 * 1000,
110
+ max: 5
111
+ });
112
+
113
+ app.post('/login', loginLimiter, loginHandler);
114
+ `);
115
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
116
+ const rateFindings = findings.filter((f) => f.id === 'RATE-001');
117
+ expect(rateFindings.length).toBe(0);
118
+ });
119
+ it('should NOT flag auth route with rateLimiter', async () => {
120
+ const file = await createTestFile('rate-limiter.ts', `
121
+ const rateLimiter = createRateLimiter();
122
+
123
+ app.post('/auth', rateLimiter, authHandler);
124
+ `);
125
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
126
+ const rateFindings = findings.filter((f) => f.id === 'RATE-001');
127
+ expect(rateFindings.length).toBe(0);
128
+ });
129
+ it('should NOT flag auth route with throttle middleware', async () => {
130
+ const file = await createTestFile('throttle.ts', `
131
+ import { throttle } from './middleware';
132
+
133
+ router.post('/login', throttle, handleLogin);
134
+ `);
135
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
136
+ const rateFindings = findings.filter((f) => f.id === 'RATE-001');
137
+ expect(rateFindings.length).toBe(0);
138
+ });
139
+ it('should NOT flag auth route with @upstash/ratelimit', async () => {
140
+ const file = await createTestFile('upstash.ts', `
141
+ import { Ratelimit } from '@upstash/ratelimit';
142
+
143
+ const ratelimit = new Ratelimit({
144
+ redis: Redis.fromEnv(),
145
+ limiter: Ratelimit.slidingWindow(10, '10 s'),
146
+ });
147
+
148
+ app.post('/register', async (req, res) => {
149
+ const { success } = await ratelimit.limit(req.ip);
150
+ if (!success) return res.status(429).send('Too many requests');
151
+ // Handle registration
152
+ });
153
+ `);
154
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
155
+ const rateFindings = findings.filter((f) => f.id === 'RATE-001');
156
+ expect(rateFindings.length).toBe(0);
157
+ });
158
+ });
159
+ describe('CORS-001: Open CORS Configuration', () => {
160
+ it('should detect cors({ origin: "*" })', async () => {
161
+ const file = await createTestFile('cors.ts', `
162
+ import cors from 'cors';
163
+
164
+ app.use(cors({
165
+ origin: "*"
166
+ }));
167
+ `);
168
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
169
+ const corsFindings = findings.filter((f) => f.id === 'CORS-001');
170
+ expect(corsFindings.length).toBeGreaterThan(0);
171
+ expect(corsFindings[0].severity).toBe('high');
172
+ });
173
+ it('should detect Access-Control-Allow-Origin: *', async () => {
174
+ const file = await createTestFile('headers.ts', `
175
+ app.use((req, res, next) => {
176
+ res.setHeader('Access-Control-Allow-Origin', '*');
177
+ next();
178
+ });
179
+ `);
180
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
181
+ expect(findings.some((f) => f.id === 'CORS-001')).toBe(true);
182
+ });
183
+ it('should detect res.header with wildcard origin', async () => {
184
+ const file = await createTestFile('wildcard.ts', `
185
+ res.header('Access-Control-Allow-Origin', '*');
186
+ `);
187
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
188
+ expect(findings.some((f) => f.id === 'CORS-001')).toBe(true);
189
+ });
190
+ it('should detect headers.set with wildcard origin', async () => {
191
+ const file = await createTestFile('headers-set.ts', `
192
+ response.headers.set('Access-Control-Allow-Origin', '*');
193
+ `);
194
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
195
+ expect(findings.some((f) => f.id === 'CORS-001')).toBe(true);
196
+ });
197
+ it('should NOT flag CORS with specific origins array', async () => {
198
+ const file = await createTestFile('safe-cors.ts', `
199
+ app.use(cors({
200
+ origin: ['https://app.example.com', 'https://admin.example.com']
201
+ }));
202
+ `);
203
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
204
+ const corsFindings = findings.filter((f) => f.id === 'CORS-001');
205
+ expect(corsFindings.length).toBe(0);
206
+ });
207
+ it('should NOT flag CORS with allowedOrigins', async () => {
208
+ const file = await createTestFile('allowed-origins.ts', `
209
+ const allowedOrigins = ['https://app.example.com'];
210
+
211
+ app.use(cors({
212
+ origin: allowedOrigins
213
+ }));
214
+ `);
215
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
216
+ const corsFindings = findings.filter((f) => f.id === 'CORS-001');
217
+ expect(corsFindings.length).toBe(0);
218
+ });
219
+ it('should NOT flag CORS with environment variable', async () => {
220
+ const file = await createTestFile('env-origin.ts', `
221
+ app.use(cors({
222
+ origin: process.env.ALLOWED_ORIGINS.split(',')
223
+ }));
224
+ `);
225
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
226
+ const corsFindings = findings.filter((f) => f.id === 'CORS-001');
227
+ expect(corsFindings.length).toBe(0);
228
+ });
229
+ it('should NOT flag CORS for public assets', async () => {
230
+ const file = await createTestFile('public-assets.ts', `
231
+ // Public assets can use wildcard CORS
232
+ app.use('/public', cors({ origin: '*' }));
233
+ `);
234
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
235
+ const corsFindings = findings.filter((f) => f.id === 'CORS-001');
236
+ expect(corsFindings.length).toBe(0);
237
+ });
238
+ });
239
+ describe('API-001: PHI in URL Query Parameters', () => {
240
+ it('should detect ?ssn= in URL', async () => {
241
+ const file = await createTestFile('phi-url.ts', `
242
+ const url = \`/api/patient?ssn=\${ssn}\`;
243
+ fetch(url);
244
+ `);
245
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
246
+ const phiFindings = findings.filter((f) => f.id === 'API-001');
247
+ expect(phiFindings.length).toBeGreaterThan(0);
248
+ expect(phiFindings[0].severity).toBe('high');
249
+ expect(phiFindings[0].category).toBe('phi-exposure');
250
+ });
251
+ it('should detect &dob= in URL', async () => {
252
+ const file = await createTestFile('dob-param.ts', `
253
+ const queryUrl = '/search?name=John&dob=1990-01-01';
254
+ `);
255
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
256
+ expect(findings.some((f) => f.id === 'API-001')).toBe(true);
257
+ });
258
+ it('should detect ?patient_name= in URL', async () => {
259
+ const file = await createTestFile('patient-name.ts', `
260
+ axios.get('/api/records?patient_name=John Doe');
261
+ `);
262
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
263
+ expect(findings.some((f) => f.id === 'API-001')).toBe(true);
264
+ });
265
+ it('should detect ?diagnosis= in URL', async () => {
266
+ const file = await createTestFile('diagnosis.ts', `
267
+ const endpoint = \`/api/search?diagnosis=\${diagnosisCode}\`;
268
+ `);
269
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
270
+ expect(findings.some((f) => f.id === 'API-001')).toBe(true);
271
+ });
272
+ it('should detect URLSearchParams with PHI', async () => {
273
+ const file = await createTestFile('search-params.ts', `
274
+ const params = new URLSearchParams();
275
+ params.append('ssn', patientSSN);
276
+ `);
277
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
278
+ expect(findings.some((f) => f.id === 'API-001')).toBe(true);
279
+ });
280
+ it('should detect searchParams.set with MRN', async () => {
281
+ const file = await createTestFile('mrn-param.ts', `
282
+ searchParams.set('mrn', medicalRecordNumber);
283
+ `);
284
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
285
+ expect(findings.some((f) => f.id === 'API-001')).toBe(true);
286
+ });
287
+ it('should NOT flag POST request with PHI in body', async () => {
288
+ const file = await createTestFile('safe-post.ts', `
289
+ const response = await fetch('/api/patient', {
290
+ method: 'POST',
291
+ body: JSON.stringify({ ssn: patientSSN })
292
+ });
293
+ `);
294
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
295
+ const phiFindings = findings.filter((f) => f.id === 'API-001');
296
+ expect(phiFindings.length).toBe(0);
297
+ });
298
+ it('should NOT flag req.body usage', async () => {
299
+ const file = await createTestFile('req-body.ts', `
300
+ app.post('/api/patient', (req, res) => {
301
+ const { ssn, dob } = req.body;
302
+ // Process PHI safely from body
303
+ });
304
+ `);
305
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
306
+ const phiFindings = findings.filter((f) => f.id === 'API-001');
307
+ expect(phiFindings.length).toBe(0);
308
+ });
309
+ it('should NOT flag comments or examples', async () => {
310
+ const file = await createTestFile('comments.ts', `
311
+ // Example: Don't use ?ssn=123-45-6789 in URLs
312
+ // TODO: Remove ?dob= from query params
313
+ `);
314
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
315
+ const phiFindings = findings.filter((f) => f.id === 'API-001');
316
+ expect(phiFindings.length).toBe(0);
317
+ });
318
+ });
319
+ describe('Combined violations', () => {
320
+ it('should detect multiple API violations in same file', async () => {
321
+ const file = await createTestFile('bad-api.ts', `
322
+ import cors from 'cors';
323
+
324
+ app.use(cors({ origin: '*' }));
325
+
326
+ app.post('/login', loginHandler);
327
+
328
+ const url = \`/api/patient?ssn=\${ssn}\`;
329
+ `);
330
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
331
+ expect(findings.some((f) => f.id === 'RATE-001')).toBe(true);
332
+ expect(findings.some((f) => f.id === 'CORS-001')).toBe(true);
333
+ expect(findings.some((f) => f.id === 'API-001')).toBe(true);
334
+ });
335
+ });
336
+ it('should provide correct HIPAA references', async () => {
337
+ const file = await createTestFile('hipaa-refs.ts', `
338
+ app.post('/login', handler);
339
+ app.use(cors({ origin: '*' }));
340
+ const url = '?ssn=123';
341
+ `);
342
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
343
+ expect(findings.every((f) => f.hipaaReference?.includes('164.312'))).toBe(true);
344
+ });
345
+ it('should have correct severity levels', async () => {
346
+ const file = await createTestFile('severity.ts', `
347
+ app.post('/login', handler);
348
+ app.use(cors({ origin: '*' }));
349
+ const url = '?ssn=123';
350
+ `);
351
+ const findings = await apiSecurityScanner.scan([file], scanOptions);
352
+ const rate001 = findings.find((f) => f.id === 'RATE-001');
353
+ const cors001 = findings.find((f) => f.id === 'CORS-001');
354
+ const api001 = findings.find((f) => f.id === 'API-001');
355
+ expect(rate001?.severity).toBe('high');
356
+ expect(cors001?.severity).toBe('high');
357
+ expect(api001?.severity).toBe('high');
358
+ });
359
+ });
360
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/scanners/api-security/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * API Security Detection Patterns
3
+ * Detects authentication routes without rate limiting, open CORS, and PHI in URLs
4
+ */
5
+ export interface ApiSecurityPattern {
6
+ id: string;
7
+ name: string;
8
+ description: string;
9
+ severity: 'high';
10
+ hipaaReference: string;
11
+ patterns: RegExp[];
12
+ negativePatterns?: RegExp[];
13
+ recommendation: string;
14
+ category: string;
15
+ }
16
+ /**
17
+ * RATE-001: Authentication Routes Without Rate Limiting
18
+ * Detects auth routes without rate limiting middleware
19
+ */
20
+ export declare const AUTH_WITHOUT_RATE_LIMIT: ApiSecurityPattern;
21
+ /**
22
+ * CORS-001: Open CORS Configuration
23
+ * Detects CORS configured with origin: "*"
24
+ */
25
+ export declare const OPEN_CORS_CONFIGURATION: ApiSecurityPattern;
26
+ /**
27
+ * API-001: PHI in URL Query Parameters
28
+ * Detects PHI data passed as URL query parameters
29
+ */
30
+ export declare const PHI_IN_URL_PARAMS: ApiSecurityPattern;
31
+ export declare const ALL_API_SECURITY_PATTERNS: ApiSecurityPattern[];
32
+ //# sourceMappingURL=patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../src/scanners/api-security/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,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,uBAAuB,EAAE,kBAmDrC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,kBAqDrC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,kBA0D/B,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,kBAAkB,EAIzD,CAAC"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * API Security Detection Patterns
3
+ * Detects authentication routes without rate limiting, open CORS, and PHI in URLs
4
+ */
5
+ /**
6
+ * RATE-001: Authentication Routes Without Rate Limiting
7
+ * Detects auth routes without rate limiting middleware
8
+ */
9
+ export const AUTH_WITHOUT_RATE_LIMIT = {
10
+ id: 'RATE-001',
11
+ name: 'Authentication Routes Without Rate Limiting',
12
+ description: 'Authentication route (/login, /signin, /auth, /register, /signup, /password-reset, /forgot-password) defined without rate limiting middleware (rateLimit, rateLimiter, throttle, slowDown, @upstash/ratelimit). Vulnerable to brute force attacks.',
13
+ severity: 'high',
14
+ hipaaReference: '45 CFR §164.312(a)(1) - Access Control',
15
+ patterns: [
16
+ // Express routes
17
+ /(?:app|router)\.(?:post|get|put|patch|delete|all)\s*\(\s*['"`]\/(?:api\/)?(?:auth|login|signin|register|signup|password-reset|forgot-password)/i,
18
+ // Next.js API routes in file path - detected separately
19
+ // This pattern won't match but we'll handle it in the scanner
20
+ // Fastify routes
21
+ /fastify\.(?:post|get|route)\s*\(\s*['"`]\/(?:api\/)?(?:auth|login|signin|register|signup|password-reset|forgot-password)/i,
22
+ // Hono routes
23
+ /app\.(?:post|get|put|patch|delete|all)\s*\(\s*['"`]\/(?:api\/)?(?:auth|login|signin|register|signup|password-reset|forgot-password)/i,
24
+ // Generic route definitions
25
+ /route\s*\(\s*['"`]\/(?:api\/)?(?:auth|login|signin|register|signup|password-reset|forgot-password)/i,
26
+ ],
27
+ negativePatterns: [
28
+ // Rate limiting middleware
29
+ /rateLimit/i,
30
+ /rateLimiter/i,
31
+ /rate-limit/i,
32
+ /throttle/i,
33
+ /slowDown/i,
34
+ /slow-down/i,
35
+ // Upstash rate limiting
36
+ /@upstash\/ratelimit/i,
37
+ /upstash.*limit/i,
38
+ // Express rate limit packages
39
+ /express-rate-limit/i,
40
+ /express-slow-down/i,
41
+ // Redis rate limiting
42
+ /redis.*limit/i,
43
+ // Custom rate limit implementations
44
+ /limitAttempts/i,
45
+ /checkRateLimit/i,
46
+ /rateLimitMiddleware/i,
47
+ ],
48
+ recommendation: 'Add rate limiting middleware to authentication routes. Example: const limiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 5 }); app.post("/login", limiter, loginHandler). Prevent brute force attacks on auth endpoints.',
49
+ category: 'access-control',
50
+ };
51
+ /**
52
+ * CORS-001: Open CORS Configuration
53
+ * Detects CORS configured with origin: "*"
54
+ */
55
+ export const OPEN_CORS_CONFIGURATION = {
56
+ id: 'CORS-001',
57
+ name: 'Open CORS Configuration (origin: "*")',
58
+ description: 'CORS configured with origin: "*" or Access-Control-Allow-Origin: *. PHI endpoints must restrict access to trusted domains only. Exposes API to cross-origin attacks from any domain.',
59
+ severity: 'high',
60
+ hipaaReference: '45 CFR §164.312(e)(1) - Transmission Security',
61
+ patterns: [
62
+ // cors({ origin: "*" })
63
+ /cors\s*\(\s*\{[^}]*origin\s*:\s*['"`]\*['"`]/i,
64
+ // cors({ origin: '*' })
65
+ /cors\s*\(\s*\{[^}]*origin\s*:\s*['"`]\*['"`]/i,
66
+ // Access-Control-Allow-Origin: *
67
+ /Access-Control-Allow-Origin['"`]?\s*[,:]?\s*['"`]\*/i,
68
+ // setHeader('Access-Control-Allow-Origin', '*')
69
+ /setHeader\s*\(\s*['"`]Access-Control-Allow-Origin['"`]\s*,\s*['"`]\*['"`]/i,
70
+ // res.header('Access-Control-Allow-Origin', '*')
71
+ /\.header\s*\(\s*['"`]Access-Control-Allow-Origin['"`]\s*,\s*['"`]\*['"`]/i,
72
+ // response.headers.set('Access-Control-Allow-Origin', '*')
73
+ /headers\.set\s*\(\s*['"`]Access-Control-Allow-Origin['"`]\s*,\s*['"`]\*['"`]/i,
74
+ ],
75
+ negativePatterns: [
76
+ // Whitelist/allowlist of specific origins
77
+ /allowedOrigins/i,
78
+ /whitelist/i,
79
+ /allowlist/i,
80
+ /trustedOrigins/i,
81
+ // Environment-based origins
82
+ /process\.env/i,
83
+ /env\.[A-Z_]*ORIGIN/i,
84
+ /ALLOWED_ORIGIN/i,
85
+ // Origin validation functions
86
+ /validateOrigin/i,
87
+ /checkOrigin/i,
88
+ // Array of origins (specific domains)
89
+ /\[.*?https?:\/\//i,
90
+ // Public assets (non-PHI endpoints)
91
+ /public/i,
92
+ /assets/i,
93
+ /static/i,
94
+ ],
95
+ recommendation: 'Restrict CORS to trusted domains. Example: cors({ origin: ["https://app.example.com", "https://admin.example.com"] }) or use environment variables: cors({ origin: process.env.ALLOWED_ORIGINS.split(",") }). Never use origin: "*" for PHI endpoints.',
96
+ category: 'access-control',
97
+ };
98
+ /**
99
+ * API-001: PHI in URL Query Parameters
100
+ * Detects PHI data passed as URL query parameters
101
+ */
102
+ export const PHI_IN_URL_PARAMS = {
103
+ id: 'API-001',
104
+ name: 'PHI Data in URL Query Parameters',
105
+ description: 'PHI data (ssn, dob, patient_name, patientName, diagnosis, medication, mrn, health_record) passed as URL query parameters (?ssn=, &dob=). URLs are logged by servers, proxies, and browsers, exposing PHI in logs.',
106
+ severity: 'high',
107
+ hipaaReference: '45 CFR §164.312(a)(1) - Access Control',
108
+ patterns: [
109
+ // Query parameter construction with PHI
110
+ /\?ssn=/i,
111
+ /&ssn=/i,
112
+ /\?dob=/i,
113
+ /&dob=/i,
114
+ /\?patient[-_]?name=/i,
115
+ /&patient[-_]?name=/i,
116
+ /\?patientName=/i,
117
+ /&patientName=/i,
118
+ /\?diagnosis=/i,
119
+ /&diagnosis=/i,
120
+ /\?medication=/i,
121
+ /&medication=/i,
122
+ /\?mrn=/i,
123
+ /&mrn=/i,
124
+ /\?health[-_]?record=/i,
125
+ /&health[-_]?record=/i,
126
+ // Template literals with PHI in query
127
+ /`[^`]*\?[^`]*(?:ssn|dob|patient[-_]?name|patientName|diagnosis|medication|mrn|health[-_]?record)=/i,
128
+ // URLSearchParams with PHI
129
+ /(?:params|searchParams|query)\.(?:append|set)\s*\(\s*['"`](?:ssn|dob|patient[-_]?name|patientName|diagnosis|medication|mrn|health[-_]?record)['"`]/i,
130
+ ],
131
+ negativePatterns: [
132
+ // POST request body (safe)
133
+ /\.post\s*\(/i,
134
+ /\.put\s*\(/i,
135
+ /\.patch\s*\(/i,
136
+ /body:/i,
137
+ /data:/i,
138
+ // Request body
139
+ /req\.body/i,
140
+ /request\.body/i,
141
+ // Comments or documentation
142
+ /\/\//,
143
+ /\/\*/,
144
+ /example/i,
145
+ /TODO/i,
146
+ // Test files
147
+ /\.test\./i,
148
+ /\.spec\./i,
149
+ /describe\(/i,
150
+ ],
151
+ recommendation: 'Never pass PHI in URL query parameters. Use POST request body instead. Example: Instead of GET /api/patient?ssn=123-45-6789, use POST /api/patient with body: { ssn: "123-45-6789" }. URLs are logged in server logs, proxy logs, and browser history.',
152
+ category: 'phi-exposure',
153
+ };
154
+ export const ALL_API_SECURITY_PATTERNS = [
155
+ AUTH_WITHOUT_RATE_LIMIT,
156
+ OPEN_CORS_CONFIGURATION,
157
+ PHI_IN_URL_PARAMS,
158
+ ];
159
+ //# sourceMappingURL=patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/scanners/api-security/patterns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Multi-Factor Authentication (MFA) Scanner
3
+ * Detects missing or bypassed MFA in authentication flows
4
+ */
5
+ import type { Scanner } from '../../types.js';
6
+ export declare const authenticationScanner: Scanner;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/authentication/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAwB,MAAM,gBAAgB,CAAC;AAGpE,eAAO,MAAM,qBAAqB,EAAE,OAwEnC,CAAC"}