verification-layer 0.19.0 → 0.21.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 +53 -0
- package/dist/cli.js +362 -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/scan.d.ts.map +1 -1
- package/dist/scan.js +3 -1
- package/dist/scan.js.map +1 -1
- 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 +313 -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 +321 -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/skills/index.d.ts +7 -0
- package/dist/scanners/skills/index.d.ts.map +1 -0
- package/dist/scanners/skills/index.js +159 -0
- package/dist/scanners/skills/index.js.map +1 -0
- package/dist/scanners/skills/patterns.d.ts +20 -0
- package/dist/scanners/skills/patterns.d.ts.map +1 -0
- package/dist/scanners/skills/patterns.js +215 -0
- package/dist/scanners/skills/patterns.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for HIPAA 2026 Security Rule Scanner
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
5
|
+
import { hipaa2026Scanner } from './index.js';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import * as os from 'os';
|
|
9
|
+
describe('HIPAA 2026 Scanner', () => {
|
|
10
|
+
let tempDir = '';
|
|
11
|
+
let testFiles = [];
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'hipaa2026-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('HIPAA-MFA-001: Multi-Factor Authentication', () => {
|
|
43
|
+
it('should detect PHI access without MFA', async () => {
|
|
44
|
+
const file = await createTestFile('auth.ts', `
|
|
45
|
+
app.post('/login', async (req, res) => {
|
|
46
|
+
const user = await authenticateUser(req.body);
|
|
47
|
+
if (user.role === 'doctor') {
|
|
48
|
+
accessPatientRecords(user);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
`);
|
|
52
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
53
|
+
const mfaFindings = findings.filter((f) => f.id === 'HIPAA-MFA-001');
|
|
54
|
+
expect(mfaFindings.length).toBeGreaterThan(0);
|
|
55
|
+
expect(mfaFindings[0].severity).toBe('critical');
|
|
56
|
+
expect(mfaFindings[0].hipaaReference).toContain('164.312(a)(2)(i)');
|
|
57
|
+
});
|
|
58
|
+
it('should not flag PHI access with MFA', async () => {
|
|
59
|
+
const file = await createTestFile('auth-secure.ts', `
|
|
60
|
+
app.post('/login', async (req, res) => {
|
|
61
|
+
const user = await authenticateUser(req.body);
|
|
62
|
+
if (!user.mfaVerified) {
|
|
63
|
+
return res.status(401).json({ error: 'MFA required' });
|
|
64
|
+
}
|
|
65
|
+
if (user.role === 'doctor') {
|
|
66
|
+
accessPatientRecords(user);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
`);
|
|
70
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
71
|
+
const mfaFindings = findings.filter((f) => f.id === 'HIPAA-MFA-001');
|
|
72
|
+
expect(mfaFindings.length).toBe(0);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('HIPAA-ENC-REST-001: Encryption at Rest', () => {
|
|
76
|
+
it('should detect database without encryption', async () => {
|
|
77
|
+
const file = await createTestFile('db.ts', `
|
|
78
|
+
import mongoose from 'mongoose';
|
|
79
|
+
|
|
80
|
+
mongoose.connect('mongodb://localhost:27017/patients', {
|
|
81
|
+
useNewUrlParser: true,
|
|
82
|
+
});
|
|
83
|
+
`);
|
|
84
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
85
|
+
const encFindings = findings.filter((f) => f.id === 'HIPAA-ENC-REST-001');
|
|
86
|
+
expect(encFindings.length).toBeGreaterThan(0);
|
|
87
|
+
expect(encFindings[0].severity).toBe('critical');
|
|
88
|
+
});
|
|
89
|
+
it('should not flag database with encryption', async () => {
|
|
90
|
+
const file = await createTestFile('db-secure.ts', `
|
|
91
|
+
import mongoose from 'mongoose';
|
|
92
|
+
|
|
93
|
+
mongoose.connect('mongodb://localhost:27017/patients', {
|
|
94
|
+
useNewUrlParser: true,
|
|
95
|
+
ssl: true,
|
|
96
|
+
encrypt: true,
|
|
97
|
+
});
|
|
98
|
+
`);
|
|
99
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
100
|
+
const encFindings = findings.filter((f) => f.id === 'HIPAA-ENC-REST-001');
|
|
101
|
+
expect(encFindings.length).toBe(0);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
describe('HIPAA-SESSION-001: Session Timeout', () => {
|
|
105
|
+
it('should detect session without timeout', async () => {
|
|
106
|
+
const file = await createTestFile('session.ts', `
|
|
107
|
+
import session from 'express-session';
|
|
108
|
+
|
|
109
|
+
app.use(session({
|
|
110
|
+
secret: 'my-secret',
|
|
111
|
+
resave: false,
|
|
112
|
+
saveUninitialized: false,
|
|
113
|
+
}));
|
|
114
|
+
`);
|
|
115
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
116
|
+
const sessionFindings = findings.filter((f) => f.id === 'HIPAA-SESSION-001');
|
|
117
|
+
expect(sessionFindings.length).toBeGreaterThan(0);
|
|
118
|
+
expect(sessionFindings[0].severity).toBe('high');
|
|
119
|
+
});
|
|
120
|
+
it('should not flag session with proper timeout', async () => {
|
|
121
|
+
const file = await createTestFile('session-secure.ts', `
|
|
122
|
+
import session from 'express-session';
|
|
123
|
+
|
|
124
|
+
app.use(session({
|
|
125
|
+
secret: 'my-secret',
|
|
126
|
+
resave: false,
|
|
127
|
+
saveUninitialized: false,
|
|
128
|
+
cookie: { maxAge: 900000 } // 15 minutes
|
|
129
|
+
}));
|
|
130
|
+
`);
|
|
131
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
132
|
+
const sessionFindings = findings.filter((f) => f.id === 'HIPAA-SESSION-001');
|
|
133
|
+
expect(sessionFindings.length).toBe(0);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
describe('HIPAA-REVOKE-001: Access Revocation', () => {
|
|
137
|
+
it('should detect user deactivation without token revocation', async () => {
|
|
138
|
+
const file = await createTestFile('user.ts', `
|
|
139
|
+
async function deactivateUser(userId: string) {
|
|
140
|
+
await User.update({ id: userId }, { active: false });
|
|
141
|
+
console.log('User deactivated');
|
|
142
|
+
}
|
|
143
|
+
`);
|
|
144
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
145
|
+
const revokeFindings = findings.filter((f) => f.id === 'HIPAA-REVOKE-001');
|
|
146
|
+
expect(revokeFindings.length).toBeGreaterThan(0);
|
|
147
|
+
expect(revokeFindings[0].severity).toBe('critical');
|
|
148
|
+
});
|
|
149
|
+
it('should not flag deactivation with token revocation', async () => {
|
|
150
|
+
const file = await createTestFile('user-secure.ts', `
|
|
151
|
+
async function deactivateUser(userId: string) {
|
|
152
|
+
await User.update({ id: userId }, { active: false });
|
|
153
|
+
await revokeAllTokens(userId);
|
|
154
|
+
await invalidateAllSessions(userId);
|
|
155
|
+
console.log('User deactivated and tokens revoked');
|
|
156
|
+
}
|
|
157
|
+
`);
|
|
158
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
159
|
+
const revokeFindings = findings.filter((f) => f.id === 'HIPAA-REVOKE-001');
|
|
160
|
+
expect(revokeFindings.length).toBe(0);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('HIPAA-BREACH-001: Breach Notification', () => {
|
|
164
|
+
it('should detect security errors without breach notification', async () => {
|
|
165
|
+
const file = await createTestFile('api.ts', `
|
|
166
|
+
try {
|
|
167
|
+
await processPhiData(data);
|
|
168
|
+
} catch (error) {
|
|
169
|
+
if (error.message.includes('unauthorized')) {
|
|
170
|
+
console.error('Security breach detected');
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
`);
|
|
174
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
175
|
+
const breachFindings = findings.filter((f) => f.id === 'HIPAA-BREACH-001');
|
|
176
|
+
expect(breachFindings.length).toBeGreaterThan(0);
|
|
177
|
+
expect(breachFindings[0].severity).toBe('critical');
|
|
178
|
+
});
|
|
179
|
+
it('should not flag errors with breach notification', async () => {
|
|
180
|
+
const file = await createTestFile('api-secure.ts', `
|
|
181
|
+
try {
|
|
182
|
+
await processPhiData(data);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
if (error.message.includes('unauthorized')) {
|
|
185
|
+
console.error('Security breach detected');
|
|
186
|
+
await notifyBreach(error);
|
|
187
|
+
await incidentResponse.trigger('security-breach');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
`);
|
|
191
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
192
|
+
const breachFindings = findings.filter((f) => f.id === 'HIPAA-BREACH-001');
|
|
193
|
+
expect(breachFindings.length).toBe(0);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
describe('HIPAA-SEGMENT-001: Network Segmentation', () => {
|
|
197
|
+
it('should detect CORS wildcard for PHI endpoints', async () => {
|
|
198
|
+
const file = await createTestFile('cors.ts', `
|
|
199
|
+
import cors from 'cors';
|
|
200
|
+
|
|
201
|
+
app.use(cors({ origin: '*' }));
|
|
202
|
+
|
|
203
|
+
app.get('/api/patients', async (req, res) => {
|
|
204
|
+
const patients = await getPatients();
|
|
205
|
+
res.json(patients);
|
|
206
|
+
});
|
|
207
|
+
`);
|
|
208
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
209
|
+
const segmentFindings = findings.filter((f) => f.id === 'HIPAA-SEGMENT-001');
|
|
210
|
+
expect(segmentFindings.length).toBeGreaterThan(0);
|
|
211
|
+
expect(segmentFindings[0].severity).toBe('critical');
|
|
212
|
+
});
|
|
213
|
+
it('should not flag CORS with origin whitelist', async () => {
|
|
214
|
+
const file = await createTestFile('cors-secure.ts', `
|
|
215
|
+
import cors from 'cors';
|
|
216
|
+
|
|
217
|
+
app.use(cors({ origin: ['https://hospital.com', 'https://ehr.hospital.com'] }));
|
|
218
|
+
|
|
219
|
+
app.get('/api/patients', async (req, res) => {
|
|
220
|
+
const patients = await getPatients();
|
|
221
|
+
res.json(patients);
|
|
222
|
+
});
|
|
223
|
+
`);
|
|
224
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
225
|
+
const segmentFindings = findings.filter((f) => f.id === 'HIPAA-SEGMENT-001');
|
|
226
|
+
expect(segmentFindings.length).toBe(0);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
describe('HIPAA-ASSET-001: Technology Asset Inventory', () => {
|
|
230
|
+
it('should generate asset inventory', async () => {
|
|
231
|
+
await createTestFile('services.ts', `
|
|
232
|
+
import mongoose from 'mongoose';
|
|
233
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
234
|
+
import axios from 'axios';
|
|
235
|
+
|
|
236
|
+
mongoose.connect('mongodb://localhost/patients');
|
|
237
|
+
const s3 = new S3Client({ region: 'us-east-1' });
|
|
238
|
+
axios.get('https://api.external.com/patient-data');
|
|
239
|
+
`);
|
|
240
|
+
const findings = await hipaa2026Scanner.scan(testFiles, scanOptions);
|
|
241
|
+
const assetFindings = findings.filter((f) => f.id === 'HIPAA-ASSET-001');
|
|
242
|
+
expect(assetFindings.length).toBe(1);
|
|
243
|
+
expect(assetFindings[0].severity).toBe('high');
|
|
244
|
+
expect(assetFindings[0].file).toBe('ASSET-INVENTORY');
|
|
245
|
+
expect(assetFindings[0].recommendation).toContain('DATABASE');
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
describe('HIPAA-FLOW-001: PHI Flow Mapping', () => {
|
|
249
|
+
it('should generate PHI flow map', async () => {
|
|
250
|
+
await createTestFile('patient-flow.ts', `
|
|
251
|
+
app.post('/api/patient', async (req, res) => {
|
|
252
|
+
const patientData = req.body.patient;
|
|
253
|
+
const validated = validatePatient(patientData);
|
|
254
|
+
await savePatient(validated);
|
|
255
|
+
return res.json({ success: true, patient: validated });
|
|
256
|
+
});
|
|
257
|
+
`);
|
|
258
|
+
const findings = await hipaa2026Scanner.scan(testFiles, scanOptions);
|
|
259
|
+
const flowFindings = findings.filter((f) => f.id === 'HIPAA-FLOW-001');
|
|
260
|
+
expect(flowFindings.length).toBe(1);
|
|
261
|
+
expect(flowFindings[0].severity).toBe('high');
|
|
262
|
+
expect(flowFindings[0].file).toBe('PHI-FLOW-MAP');
|
|
263
|
+
expect(flowFindings[0].recommendation).toContain('INPUT');
|
|
264
|
+
expect(flowFindings[0].recommendation).toContain('PROCESSING');
|
|
265
|
+
expect(flowFindings[0].recommendation).toContain('STORAGE');
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
describe('HIPAA-PENTEST-001: Vulnerability Scanning', () => {
|
|
269
|
+
it('should detect missing vulnerability scanning config', async () => {
|
|
270
|
+
const file = await createTestFile('package.json', JSON.stringify({
|
|
271
|
+
name: 'test-app',
|
|
272
|
+
version: '1.0.0',
|
|
273
|
+
scripts: {
|
|
274
|
+
test: 'jest',
|
|
275
|
+
},
|
|
276
|
+
}));
|
|
277
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
278
|
+
const pentestFindings = findings.filter((f) => f.id === 'HIPAA-PENTEST-001');
|
|
279
|
+
expect(pentestFindings.length).toBeGreaterThan(0);
|
|
280
|
+
expect(pentestFindings[0].severity).toBe('high');
|
|
281
|
+
});
|
|
282
|
+
it('should not flag when dependabot exists', async () => {
|
|
283
|
+
const githubDir = path.join(tempDir, '.github');
|
|
284
|
+
await fs.mkdir(githubDir, { recursive: true });
|
|
285
|
+
await fs.writeFile(path.join(githubDir, 'dependabot.yml'), 'version: 2\nupdates:\n - package-ecosystem: npm', 'utf-8');
|
|
286
|
+
const file = await createTestFile('package.json', JSON.stringify({
|
|
287
|
+
name: 'test-app',
|
|
288
|
+
version: '1.0.0',
|
|
289
|
+
}));
|
|
290
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
291
|
+
const pentestFindings = findings.filter((f) => f.id === 'HIPAA-PENTEST-001');
|
|
292
|
+
expect(pentestFindings.length).toBe(0);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
describe('General Scanner Behavior', () => {
|
|
296
|
+
it('should only scan code files', async () => {
|
|
297
|
+
await createTestFile('README.md', 'patient data here');
|
|
298
|
+
await createTestFile('data.json', '{"patient": "data"}');
|
|
299
|
+
await createTestFile('code.ts', 'const patient = req.body;');
|
|
300
|
+
const findings = await hipaa2026Scanner.scan(testFiles, scanOptions);
|
|
301
|
+
// Should only find findings in code.ts
|
|
302
|
+
const uniqueFiles = new Set(findings.map((f) => path.basename(f.file)));
|
|
303
|
+
expect(uniqueFiles.has('README.md')).toBe(false);
|
|
304
|
+
expect(uniqueFiles.has('data.json')).toBe(false);
|
|
305
|
+
});
|
|
306
|
+
it('should include confidence scores', async () => {
|
|
307
|
+
const file = await createTestFile('auth.ts', `
|
|
308
|
+
app.post('/login', async (req) => {
|
|
309
|
+
const user = await authenticateUser(req.body);
|
|
310
|
+
accessPatientRecords(user);
|
|
311
|
+
});
|
|
312
|
+
`);
|
|
313
|
+
const findings = await hipaa2026Scanner.scan([file], scanOptions);
|
|
314
|
+
for (const finding of findings) {
|
|
315
|
+
expect(finding.confidence).toBeDefined();
|
|
316
|
+
expect(['high', 'medium', 'low']).toContain(finding.confidence);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/scanners/hipaa2026/index.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HIPAA 2026 Security Rule Detection Patterns
|
|
3
|
+
* Covers 15 technical requirements (all now "required" instead of "addressable")
|
|
4
|
+
* Expected enforcement: May 2026
|
|
5
|
+
*/
|
|
6
|
+
export interface HIPAA2026Pattern {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
severity: 'critical' | 'high';
|
|
11
|
+
hipaaReference: string;
|
|
12
|
+
patterns: RegExp[];
|
|
13
|
+
negativePatterns?: RegExp[];
|
|
14
|
+
autoFix?: string;
|
|
15
|
+
confidence: 'high' | 'medium' | 'low';
|
|
16
|
+
category: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* HIPAA-MFA-001: Multi-Factor Authentication Enforcement
|
|
20
|
+
*/
|
|
21
|
+
export declare const MFA_PATTERNS: HIPAA2026Pattern;
|
|
22
|
+
/**
|
|
23
|
+
* HIPAA-ENC-REST-001: Encryption at Rest
|
|
24
|
+
*/
|
|
25
|
+
export declare const ENCRYPTION_AT_REST_PATTERNS: HIPAA2026Pattern;
|
|
26
|
+
/**
|
|
27
|
+
* HIPAA-SESSION-001: Automatic Session Timeout
|
|
28
|
+
*/
|
|
29
|
+
export declare const SESSION_TIMEOUT_PATTERNS: HIPAA2026Pattern;
|
|
30
|
+
/**
|
|
31
|
+
* HIPAA-REVOKE-001: Immediate Access Revocation
|
|
32
|
+
*/
|
|
33
|
+
export declare const ACCESS_REVOCATION_PATTERNS: HIPAA2026Pattern;
|
|
34
|
+
/**
|
|
35
|
+
* HIPAA-BREACH-001: 24-Hour Breach Notification
|
|
36
|
+
*/
|
|
37
|
+
export declare const BREACH_NOTIFICATION_PATTERNS: HIPAA2026Pattern;
|
|
38
|
+
/**
|
|
39
|
+
* HIPAA-SEGMENT-001: Network Segmentation
|
|
40
|
+
*/
|
|
41
|
+
export declare const NETWORK_SEGMENTATION_PATTERNS: HIPAA2026Pattern;
|
|
42
|
+
/**
|
|
43
|
+
* HIPAA-ASSET-001: Technology Asset Inventory
|
|
44
|
+
* Special pattern - triggers asset inventory generation
|
|
45
|
+
*/
|
|
46
|
+
export declare const ASSET_INVENTORY_PATTERNS: HIPAA2026Pattern;
|
|
47
|
+
/**
|
|
48
|
+
* HIPAA-FLOW-001: ePHI Flow Mapping
|
|
49
|
+
* Special pattern - triggers flow map generation
|
|
50
|
+
*/
|
|
51
|
+
export declare const PHI_FLOW_MAPPING_PATTERNS: HIPAA2026Pattern;
|
|
52
|
+
/**
|
|
53
|
+
* HIPAA-PENTEST-001: Vulnerability Scanning Configuration
|
|
54
|
+
*/
|
|
55
|
+
export declare const VULNERABILITY_SCANNING_PATTERNS: HIPAA2026Pattern;
|
|
56
|
+
export declare const ALL_HIPAA_2026_PATTERNS: HIPAA2026Pattern[];
|
|
57
|
+
//# sourceMappingURL=patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../src/scanners/hipaa2026/patterns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,UAAU,GAAG,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,gBA2B1B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAE,gBA6BzC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,gBA0BtC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,EAAE,gBAyBxC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,EAAE,gBAuB1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,6BAA6B,EAAE,gBAyB3C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,gBAmBtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,gBAmBvC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,+BAA+B,EAAE,gBAoB7C,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAUrD,CAAC"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HIPAA 2026 Security Rule Detection Patterns
|
|
3
|
+
* Covers 15 technical requirements (all now "required" instead of "addressable")
|
|
4
|
+
* Expected enforcement: May 2026
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* HIPAA-MFA-001: Multi-Factor Authentication Enforcement
|
|
8
|
+
*/
|
|
9
|
+
export const MFA_PATTERNS = {
|
|
10
|
+
id: 'HIPAA-MFA-001',
|
|
11
|
+
name: 'Missing Multi-Factor Authentication for PHI Access',
|
|
12
|
+
description: 'Endpoints accessing PHI must enforce MFA. All auth configs must require multi-factor authentication.',
|
|
13
|
+
severity: 'critical',
|
|
14
|
+
hipaaReference: '45 CFR §164.312(a)(2)(i) - Access Control (Required)',
|
|
15
|
+
patterns: [
|
|
16
|
+
// Login/auth without MFA
|
|
17
|
+
/(?:login|authenticate|signin|auth).*?(?:patient|phi|medical|health)(?!.*?(?:mfa|multi.?factor|2fa|totp|authenticator))/i,
|
|
18
|
+
// Auth configs without MFA
|
|
19
|
+
/(?:passport|auth0|okta|cognito)\.(?:use|configure).*?(?!.*?(?:mfa|multiFactor|requireMFA))/i,
|
|
20
|
+
// Admin endpoints without MFA
|
|
21
|
+
/\/admin.*?(?:patient|medical|phi)(?!.*?(?:mfa|2fa))/i,
|
|
22
|
+
// Session creation without MFA
|
|
23
|
+
/createSession.*?(?:user|admin)(?!.*?mfaVerified)/i,
|
|
24
|
+
// JWT without MFA claim
|
|
25
|
+
/jwt\.sign\(.*?(?:patient|phi)(?!.*?mfaVerified)/i,
|
|
26
|
+
],
|
|
27
|
+
negativePatterns: [
|
|
28
|
+
/requireMFA:\s*true/i,
|
|
29
|
+
/mfaVerified/i,
|
|
30
|
+
/authenticator\.verify/i,
|
|
31
|
+
/totp\.validate/i,
|
|
32
|
+
],
|
|
33
|
+
autoFix: 'Add MFA enforcement: requireMFA: true, verify TOTP/authenticator before granting access',
|
|
34
|
+
confidence: 'high',
|
|
35
|
+
category: 'access-control',
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* HIPAA-ENC-REST-001: Encryption at Rest
|
|
39
|
+
*/
|
|
40
|
+
export const ENCRYPTION_AT_REST_PATTERNS = {
|
|
41
|
+
id: 'HIPAA-ENC-REST-001',
|
|
42
|
+
name: 'ePHI Stored Without Encryption at Rest',
|
|
43
|
+
description: 'All ePHI must be encrypted at rest using AES-256 or stronger.',
|
|
44
|
+
severity: 'critical',
|
|
45
|
+
hipaaReference: '45 CFR §164.312(a)(2)(iv) - Encryption (Required)',
|
|
46
|
+
patterns: [
|
|
47
|
+
// Database without encryption
|
|
48
|
+
/(?:mongoose|sequelize|typeorm|prisma)\.(?:connect|createConnection).*?(?!.*?(?:encrypt|ssl|tls))/i,
|
|
49
|
+
// File storage without encryption
|
|
50
|
+
/(?:fs\.writeFile|writeFileSync|s3\.putObject).*?(?:patient|phi|medical)(?!.*?(?:encrypt|cipher))/i,
|
|
51
|
+
// LocalStorage with PHI
|
|
52
|
+
/localStorage\.setItem.*?(?:patient|ssn|mrn|phi)/i,
|
|
53
|
+
// Cookie with PHI unencrypted
|
|
54
|
+
/(?:res\.cookie|setCookie).*?(?:patient|phi|medical)(?!.*?(?:encrypt|secure|httpOnly))/i,
|
|
55
|
+
// MongoDB without encryption
|
|
56
|
+
/MongoClient\.connect.*?(?!.*?(?:ssl|tls|encryption))/i,
|
|
57
|
+
// PostgreSQL without encryption
|
|
58
|
+
/(?:pg|postgres)\.(?:connect|Pool).*?(?!.*?ssl)/i,
|
|
59
|
+
],
|
|
60
|
+
negativePatterns: [
|
|
61
|
+
/encrypt:\s*true/i,
|
|
62
|
+
/ssl:\s*true/i,
|
|
63
|
+
/cipher\./i,
|
|
64
|
+
/aes-256/i,
|
|
65
|
+
],
|
|
66
|
+
autoFix: 'Enable encryption at rest: Set encrypt: true in DB config, use crypto.cipher for file storage',
|
|
67
|
+
confidence: 'high',
|
|
68
|
+
category: 'encryption',
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* HIPAA-SESSION-001: Automatic Session Timeout
|
|
72
|
+
*/
|
|
73
|
+
export const SESSION_TIMEOUT_PATTERNS = {
|
|
74
|
+
id: 'HIPAA-SESSION-001',
|
|
75
|
+
name: 'Missing Automatic Session Timeout',
|
|
76
|
+
description: 'PHI access sessions must auto-expire within 15 minutes of inactivity.',
|
|
77
|
+
severity: 'high',
|
|
78
|
+
hipaaReference: '45 CFR §164.312(a)(2)(iii) - Session Control (Required)',
|
|
79
|
+
patterns: [
|
|
80
|
+
// Session config without expiration
|
|
81
|
+
/(?:express-session|session)\.(?:configure|use)(?!.*?(?:maxAge|expires|timeout))/i,
|
|
82
|
+
// Session with timeout > 15 min (900000 ms)
|
|
83
|
+
/maxAge:\s*(?:9[0-9]{5}[0-9]+|[1-9][0-9]{6,})/i,
|
|
84
|
+
// JWT without expiration
|
|
85
|
+
/jwt\.sign\([^)]*(?!.*?expiresIn)/i,
|
|
86
|
+
// Cookie session without expiration
|
|
87
|
+
/cookie-session.*?(?!.*?maxAge)/i,
|
|
88
|
+
// Missing idle timeout
|
|
89
|
+
/session.*?(?!.*?(?:idle|inactivity).*?timeout)/i,
|
|
90
|
+
],
|
|
91
|
+
negativePatterns: [
|
|
92
|
+
/maxAge:\s*[1-8][0-9]{5}/i, // <= 900000 (15 min)
|
|
93
|
+
/expiresIn:\s*['"](?:1[0-5]m|[1-9]m)['"]/i,
|
|
94
|
+
/idleTimeout/i,
|
|
95
|
+
],
|
|
96
|
+
autoFix: 'Set session timeout: maxAge: 900000 (15 min), implement idle timeout detector',
|
|
97
|
+
confidence: 'high',
|
|
98
|
+
category: 'access-control',
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* HIPAA-REVOKE-001: Immediate Access Revocation
|
|
102
|
+
*/
|
|
103
|
+
export const ACCESS_REVOCATION_PATTERNS = {
|
|
104
|
+
id: 'HIPAA-REVOKE-001',
|
|
105
|
+
name: 'Missing Immediate Access Revocation',
|
|
106
|
+
description: 'User deactivation must immediately invalidate all sessions and tokens.',
|
|
107
|
+
severity: 'critical',
|
|
108
|
+
hipaaReference: '45 CFR §164.308(a)(3)(ii)(C) - Termination Procedures (Required)',
|
|
109
|
+
patterns: [
|
|
110
|
+
// Deactivate user without token revocation
|
|
111
|
+
/(?:deactivate|disable|remove)User(?!.*?(?:revoke|invalidate|blacklist).*?(?:token|session))/i,
|
|
112
|
+
// Delete user without session cleanup
|
|
113
|
+
/(?:deleteUser|removeUser).*?(?!.*?(?:logout|invalidate|clearSessions))/i,
|
|
114
|
+
// Missing token blacklist
|
|
115
|
+
/(?:user|admin).*?(?:deactivat|terminat).*?(?!.*?blacklist)/i,
|
|
116
|
+
// Role change without re-auth
|
|
117
|
+
/(?:updateRole|changePermissions)(?!.*?(?:logout|reauth|invalidate))/i,
|
|
118
|
+
],
|
|
119
|
+
negativePatterns: [
|
|
120
|
+
/revokeAllTokens/i,
|
|
121
|
+
/invalidateAllSessions/i,
|
|
122
|
+
/tokenBlacklist\.add/i,
|
|
123
|
+
/clearUserSessions/i,
|
|
124
|
+
],
|
|
125
|
+
autoFix: 'Add token revocation: Call revokeAllTokens() and invalidateAllSessions() on user deactivation',
|
|
126
|
+
confidence: 'medium',
|
|
127
|
+
category: 'access-control',
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* HIPAA-BREACH-001: 24-Hour Breach Notification
|
|
131
|
+
*/
|
|
132
|
+
export const BREACH_NOTIFICATION_PATTERNS = {
|
|
133
|
+
id: 'HIPAA-BREACH-001',
|
|
134
|
+
name: 'Missing Breach Notification Mechanism',
|
|
135
|
+
description: 'Must have automated breach detection and notification within 24 hours.',
|
|
136
|
+
severity: 'critical',
|
|
137
|
+
hipaaReference: '45 CFR §164.308(a)(6)(ii) - Security Incident Procedures (Required)',
|
|
138
|
+
patterns: [
|
|
139
|
+
// Security errors without breach handler
|
|
140
|
+
/catch\s*\(.*?error.*?\).*?(?:security|unauthorized|breach)(?!.*?(?:notifyBreach|incidentResponse|alertSecurity))/i,
|
|
141
|
+
// Failed login attempts without monitoring
|
|
142
|
+
/(?:failed|invalid).*?(?:login|auth)(?!.*?(?:monitor|alert|notify))/i,
|
|
143
|
+
// Data access anomaly without alert
|
|
144
|
+
/(?:unusual|suspicious).*?access(?!.*?(?:alert|notify|incident))/i,
|
|
145
|
+
],
|
|
146
|
+
negativePatterns: [
|
|
147
|
+
/breachNotification\./i,
|
|
148
|
+
/incidentResponse\.trigger/i,
|
|
149
|
+
/securityAlert\.send/i,
|
|
150
|
+
/notifyBreach/i,
|
|
151
|
+
],
|
|
152
|
+
autoFix: 'Implement breach notification: Create incident response handler, set up 24h alert system',
|
|
153
|
+
confidence: 'medium',
|
|
154
|
+
category: 'audit-logging',
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* HIPAA-SEGMENT-001: Network Segmentation
|
|
158
|
+
*/
|
|
159
|
+
export const NETWORK_SEGMENTATION_PATTERNS = {
|
|
160
|
+
id: 'HIPAA-SEGMENT-001',
|
|
161
|
+
name: 'Missing Network Segmentation for PHI',
|
|
162
|
+
description: 'PHI services must be network-segmented with restricted CORS and firewall rules.',
|
|
163
|
+
severity: 'critical',
|
|
164
|
+
hipaaReference: '45 CFR §164.312(e)(1) - Transmission Security (Required)',
|
|
165
|
+
patterns: [
|
|
166
|
+
// CORS allowing all origins for PHI
|
|
167
|
+
/cors\(\{?\s*origin:\s*['"]?\*['"]?.*?(?:patient|phi|medical)/i,
|
|
168
|
+
// PHI API without network restrictions
|
|
169
|
+
/\/api.*?(?:patient|phi|medical)(?!.*?(?:firewall|vpc|subnet|private))/i,
|
|
170
|
+
// Internal PHI service publicly accessible
|
|
171
|
+
/(?:express|fastify|koa)\.listen.*?(?:patient|phi)(?!.*?(?:localhost|127\.0\.0\.1|private))/i,
|
|
172
|
+
// Missing VPC/subnet config
|
|
173
|
+
/(?:database|storage).*?(?:patient|phi)(?!.*?(?:vpc|subnet|securityGroup))/i,
|
|
174
|
+
],
|
|
175
|
+
negativePatterns: [
|
|
176
|
+
/origin:\s*\[.*?\]/i, // Whitelist
|
|
177
|
+
/private.*?subnet/i,
|
|
178
|
+
/securityGroup/i,
|
|
179
|
+
/firewall.*?rules/i,
|
|
180
|
+
],
|
|
181
|
+
autoFix: 'Implement network segmentation: Use VPC/subnet isolation, restrict CORS to whitelisted origins',
|
|
182
|
+
confidence: 'high',
|
|
183
|
+
category: 'access-control',
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* HIPAA-ASSET-001: Technology Asset Inventory
|
|
187
|
+
* Special pattern - triggers asset inventory generation
|
|
188
|
+
*/
|
|
189
|
+
export const ASSET_INVENTORY_PATTERNS = {
|
|
190
|
+
id: 'HIPAA-ASSET-001',
|
|
191
|
+
name: 'Generate ePHI Technology Asset Inventory',
|
|
192
|
+
description: 'Automatic inventory of all systems processing, storing, or transmitting ePHI.',
|
|
193
|
+
severity: 'high',
|
|
194
|
+
hipaaReference: '45 CFR §164.308(a)(1)(ii)(A) - Risk Analysis (Required)',
|
|
195
|
+
patterns: [
|
|
196
|
+
// Databases
|
|
197
|
+
/(?:mongoose|sequelize|prisma|typeorm|knex)\.(?:connect|model)/i,
|
|
198
|
+
// Storage services
|
|
199
|
+
/(?:s3|azure\.storage|gcs)\./i,
|
|
200
|
+
// Third-party integrations
|
|
201
|
+
/(?:stripe|twilio|sendgrid|mailgun)\.(?:api|client)/i,
|
|
202
|
+
// APIs
|
|
203
|
+
/(?:axios|fetch|got|request)\./i,
|
|
204
|
+
],
|
|
205
|
+
autoFix: 'Asset inventory will be generated automatically in scan report',
|
|
206
|
+
confidence: 'high',
|
|
207
|
+
category: 'data-retention',
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* HIPAA-FLOW-001: ePHI Flow Mapping
|
|
211
|
+
* Special pattern - triggers flow map generation
|
|
212
|
+
*/
|
|
213
|
+
export const PHI_FLOW_MAPPING_PATTERNS = {
|
|
214
|
+
id: 'HIPAA-FLOW-001',
|
|
215
|
+
name: 'Generate ePHI Flow Map',
|
|
216
|
+
description: 'Automatic mapping of PHI data flow through system (input → processing → storage → output).',
|
|
217
|
+
severity: 'high',
|
|
218
|
+
hipaaReference: '45 CFR §164.308(a)(1)(ii)(A) - Risk Analysis (Required)',
|
|
219
|
+
patterns: [
|
|
220
|
+
// Input points
|
|
221
|
+
/(?:req\.body|req\.params|req\.query).*?(?:patient|phi|medical)/i,
|
|
222
|
+
// Processing
|
|
223
|
+
/(?:process|transform|validate).*?(?:patient|phi)/i,
|
|
224
|
+
// Storage
|
|
225
|
+
/(?:save|insert|update).*?(?:patient|phi)/i,
|
|
226
|
+
// Output
|
|
227
|
+
/(?:res\.(?:send|json)|return).*?(?:patient|phi)/i,
|
|
228
|
+
],
|
|
229
|
+
autoFix: 'PHI flow map will be generated automatically in scan report',
|
|
230
|
+
confidence: 'high',
|
|
231
|
+
category: 'data-retention',
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* HIPAA-PENTEST-001: Vulnerability Scanning Configuration
|
|
235
|
+
*/
|
|
236
|
+
export const VULNERABILITY_SCANNING_PATTERNS = {
|
|
237
|
+
id: 'HIPAA-PENTEST-001',
|
|
238
|
+
name: 'Missing Vulnerability Scanning Configuration',
|
|
239
|
+
description: 'Must have automated vulnerability scanning (Dependabot, Snyk, Trivy) in CI/CD.',
|
|
240
|
+
severity: 'high',
|
|
241
|
+
hipaaReference: '45 CFR §164.308(a)(8) - Evaluation (Required)',
|
|
242
|
+
patterns: [
|
|
243
|
+
// Missing security scanning configs
|
|
244
|
+
/package\.json(?!.*?(?:snyk|audit|vulnerability))/i,
|
|
245
|
+
],
|
|
246
|
+
negativePatterns: [
|
|
247
|
+
/dependabot\.yml/i,
|
|
248
|
+
/snyk\.yml/i,
|
|
249
|
+
/trivy/i,
|
|
250
|
+
/npm audit/i,
|
|
251
|
+
/security.*?scan/i,
|
|
252
|
+
],
|
|
253
|
+
autoFix: 'Add vulnerability scanning: Enable Dependabot, add Snyk/Trivy to CI/CD pipeline',
|
|
254
|
+
confidence: 'medium',
|
|
255
|
+
category: 'audit-logging',
|
|
256
|
+
};
|
|
257
|
+
export const ALL_HIPAA_2026_PATTERNS = [
|
|
258
|
+
MFA_PATTERNS,
|
|
259
|
+
ENCRYPTION_AT_REST_PATTERNS,
|
|
260
|
+
SESSION_TIMEOUT_PATTERNS,
|
|
261
|
+
ACCESS_REVOCATION_PATTERNS,
|
|
262
|
+
BREACH_NOTIFICATION_PATTERNS,
|
|
263
|
+
NETWORK_SEGMENTATION_PATTERNS,
|
|
264
|
+
ASSET_INVENTORY_PATTERNS,
|
|
265
|
+
PHI_FLOW_MAPPING_PATTERNS,
|
|
266
|
+
VULNERABILITY_SCANNING_PATTERNS,
|
|
267
|
+
];
|
|
268
|
+
//# sourceMappingURL=patterns.js.map
|