verification-layer 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +251 -615
- package/dist/cli.js +542 -0
- package/dist/cli.js.map +1 -1
- package/dist/marketplace/index.d.ts +8 -0
- package/dist/marketplace/index.d.ts.map +1 -0
- package/dist/marketplace/index.js +7 -0
- package/dist/marketplace/index.js.map +1 -0
- package/dist/marketplace/installer.d.ts +62 -0
- package/dist/marketplace/installer.d.ts.map +1 -0
- package/dist/marketplace/installer.js +254 -0
- package/dist/marketplace/installer.js.map +1 -0
- package/dist/marketplace/registry.d.ts +52 -0
- package/dist/marketplace/registry.d.ts.map +1 -0
- package/dist/marketplace/registry.js +759 -0
- package/dist/marketplace/registry.js.map +1 -0
- package/dist/marketplace/types.d.ts +123 -0
- package/dist/marketplace/types.d.ts.map +1 -0
- package/dist/marketplace/types.js +6 -0
- package/dist/marketplace/types.js.map +1 -0
- package/dist/reporters/audit-report.d.ts.map +1 -1
- package/dist/reporters/audit-report.js +180 -0
- package/dist/reporters/audit-report.js.map +1 -1
- package/dist/reporters/index.d.ts.map +1 -1
- package/dist/reporters/index.js +2612 -5
- package/dist/reporters/index.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +15 -1
- package/dist/scan.js.map +1 -1
- package/dist/scanners/api-security/index.d.ts +7 -0
- package/dist/scanners/api-security/index.d.ts.map +1 -0
- package/dist/scanners/api-security/index.js +139 -0
- package/dist/scanners/api-security/index.js.map +1 -0
- package/dist/scanners/api-security/index.test.d.ts +5 -0
- package/dist/scanners/api-security/index.test.d.ts.map +1 -0
- package/dist/scanners/api-security/index.test.js +360 -0
- package/dist/scanners/api-security/index.test.js.map +1 -0
- package/dist/scanners/api-security/patterns.d.ts +32 -0
- package/dist/scanners/api-security/patterns.d.ts.map +1 -0
- package/dist/scanners/api-security/patterns.js +159 -0
- package/dist/scanners/api-security/patterns.js.map +1 -0
- package/dist/scanners/authentication/index.d.ts +7 -0
- package/dist/scanners/authentication/index.d.ts.map +1 -0
- package/dist/scanners/authentication/index.js +107 -0
- package/dist/scanners/authentication/index.js.map +1 -0
- package/dist/scanners/authentication/index.test.d.ts +5 -0
- package/dist/scanners/authentication/index.test.d.ts.map +1 -0
- package/dist/scanners/authentication/index.test.js +379 -0
- package/dist/scanners/authentication/index.test.js.map +1 -0
- package/dist/scanners/authentication/patterns.d.ts +32 -0
- package/dist/scanners/authentication/patterns.d.ts.map +1 -0
- package/dist/scanners/authentication/patterns.js +133 -0
- package/dist/scanners/authentication/patterns.js.map +1 -0
- package/dist/scanners/configuration/index.d.ts +8 -0
- package/dist/scanners/configuration/index.d.ts.map +1 -0
- package/dist/scanners/configuration/index.js +87 -0
- package/dist/scanners/configuration/index.js.map +1 -0
- package/dist/scanners/configuration/index.test.d.ts +5 -0
- package/dist/scanners/configuration/index.test.d.ts.map +1 -0
- package/dist/scanners/configuration/index.test.js +344 -0
- package/dist/scanners/configuration/index.test.js.map +1 -0
- package/dist/scanners/configuration/patterns.d.ts +32 -0
- package/dist/scanners/configuration/patterns.d.ts.map +1 -0
- package/dist/scanners/configuration/patterns.js +146 -0
- package/dist/scanners/configuration/patterns.js.map +1 -0
- package/dist/scanners/credentials/index.d.ts +7 -0
- package/dist/scanners/credentials/index.d.ts.map +1 -0
- package/dist/scanners/credentials/index.js +129 -0
- package/dist/scanners/credentials/index.js.map +1 -0
- package/dist/scanners/credentials/index.test.d.ts +5 -0
- package/dist/scanners/credentials/index.test.d.ts.map +1 -0
- package/dist/scanners/credentials/index.test.js +395 -0
- package/dist/scanners/credentials/index.test.js.map +1 -0
- package/dist/scanners/credentials/patterns.d.ts +32 -0
- package/dist/scanners/credentials/patterns.d.ts.map +1 -0
- package/dist/scanners/credentials/patterns.js +140 -0
- package/dist/scanners/credentials/patterns.js.map +1 -0
- package/dist/scanners/errors/index.d.ts +8 -0
- package/dist/scanners/errors/index.d.ts.map +1 -0
- package/dist/scanners/errors/index.js +78 -0
- package/dist/scanners/errors/index.js.map +1 -0
- package/dist/scanners/errors/index.test.d.ts +5 -0
- package/dist/scanners/errors/index.test.d.ts.map +1 -0
- package/dist/scanners/errors/index.test.js +330 -0
- package/dist/scanners/errors/index.test.js.map +1 -0
- package/dist/scanners/errors/patterns.d.ts +27 -0
- package/dist/scanners/errors/patterns.d.ts.map +1 -0
- package/dist/scanners/errors/patterns.js +97 -0
- package/dist/scanners/errors/patterns.js.map +1 -0
- package/dist/scanners/hipaa2026/index.d.ts +8 -0
- package/dist/scanners/hipaa2026/index.d.ts.map +1 -0
- package/dist/scanners/hipaa2026/index.js +345 -0
- package/dist/scanners/hipaa2026/index.js.map +1 -0
- package/dist/scanners/hipaa2026/index.test.d.ts +5 -0
- package/dist/scanners/hipaa2026/index.test.d.ts.map +1 -0
- package/dist/scanners/hipaa2026/index.test.js +332 -0
- package/dist/scanners/hipaa2026/index.test.js.map +1 -0
- package/dist/scanners/hipaa2026/patterns.d.ts +57 -0
- package/dist/scanners/hipaa2026/patterns.d.ts.map +1 -0
- package/dist/scanners/hipaa2026/patterns.js +268 -0
- package/dist/scanners/hipaa2026/patterns.js.map +1 -0
- package/dist/scanners/operational/index.d.ts +7 -0
- package/dist/scanners/operational/index.d.ts.map +1 -0
- package/dist/scanners/operational/index.js +171 -0
- package/dist/scanners/operational/index.js.map +1 -0
- package/dist/scanners/operational/index.test.d.ts +5 -0
- package/dist/scanners/operational/index.test.d.ts.map +1 -0
- package/dist/scanners/operational/index.test.js +406 -0
- package/dist/scanners/operational/index.test.js.map +1 -0
- package/dist/scanners/operational/patterns.d.ts +33 -0
- package/dist/scanners/operational/patterns.d.ts.map +1 -0
- package/dist/scanners/operational/patterns.js +151 -0
- package/dist/scanners/operational/patterns.js.map +1 -0
- package/dist/scanners/rbac/index.d.ts +7 -0
- package/dist/scanners/rbac/index.d.ts.map +1 -0
- package/dist/scanners/rbac/index.js +145 -0
- package/dist/scanners/rbac/index.js.map +1 -0
- package/dist/scanners/rbac/index.test.d.ts +5 -0
- package/dist/scanners/rbac/index.test.d.ts.map +1 -0
- package/dist/scanners/rbac/index.test.js +422 -0
- package/dist/scanners/rbac/index.test.js.map +1 -0
- package/dist/scanners/rbac/patterns.d.ts +32 -0
- package/dist/scanners/rbac/patterns.d.ts.map +1 -0
- package/dist/scanners/rbac/patterns.js +124 -0
- package/dist/scanners/rbac/patterns.js.map +1 -0
- package/dist/scanners/revocation/index.d.ts +8 -0
- package/dist/scanners/revocation/index.d.ts.map +1 -0
- package/dist/scanners/revocation/index.js +83 -0
- package/dist/scanners/revocation/index.js.map +1 -0
- package/dist/scanners/revocation/index.test.d.ts +5 -0
- package/dist/scanners/revocation/index.test.d.ts.map +1 -0
- package/dist/scanners/revocation/index.test.js +332 -0
- package/dist/scanners/revocation/index.test.js.map +1 -0
- package/dist/scanners/revocation/patterns.d.ts +27 -0
- package/dist/scanners/revocation/patterns.d.ts.map +1 -0
- package/dist/scanners/revocation/patterns.js +109 -0
- package/dist/scanners/revocation/patterns.js.map +1 -0
- package/dist/scanners/sanitization/index.d.ts +8 -0
- package/dist/scanners/sanitization/index.d.ts.map +1 -0
- package/dist/scanners/sanitization/index.js +98 -0
- package/dist/scanners/sanitization/index.js.map +1 -0
- package/dist/scanners/sanitization/index.test.d.ts +5 -0
- package/dist/scanners/sanitization/index.test.d.ts.map +1 -0
- package/dist/scanners/sanitization/index.test.js +370 -0
- package/dist/scanners/sanitization/index.test.js.map +1 -0
- package/dist/scanners/sanitization/patterns.d.ts +27 -0
- package/dist/scanners/sanitization/patterns.d.ts.map +1 -0
- package/dist/scanners/sanitization/patterns.js +117 -0
- package/dist/scanners/sanitization/patterns.js.map +1 -0
- package/dist/training/certificate.d.ts +26 -0
- package/dist/training/certificate.d.ts.map +1 -0
- package/dist/training/certificate.js +92 -0
- package/dist/training/certificate.js.map +1 -0
- package/dist/training/index.d.ts +3 -0
- package/dist/training/index.d.ts.map +1 -0
- package/dist/training/index.js +243 -0
- package/dist/training/index.js.map +1 -0
- package/dist/training/modules.d.ts +13 -0
- package/dist/training/modules.d.ts.map +1 -0
- package/dist/training/modules.js +608 -0
- package/dist/training/modules.js.map +1 -0
- package/dist/training/questions.d.ts +9 -0
- package/dist/training/questions.d.ts.map +1 -0
- package/dist/training/questions.js +505 -0
- package/dist/training/questions.js.map +1 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/npm-audit.d.ts +6 -0
- package/dist/utils/npm-audit.d.ts.map +1 -0
- package/dist/utils/npm-audit.js +95 -0
- package/dist/utils/npm-audit.js.map +1 -0
- package/dist/utils/scan-history.d.ts +59 -0
- package/dist/utils/scan-history.d.ts.map +1 -0
- package/dist/utils/scan-history.js +170 -0
- package/dist/utils/scan-history.js.map +1 -0
- package/package.json +4 -1
- package/templates/baa-verification-letter.md +105 -0
- package/templates/irp.md +545 -0
- package/templates/notice-of-privacy-practices.md +491 -0
- package/templates/physical-safeguards-checklist.md +247 -0
- package/templates/security-officer-designation.md +237 -0
|
@@ -0,0 +1,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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/scanners/hipaa2026/patterns.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiBH;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAqB;IAC5C,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,oDAAoD;IAC1D,WAAW,EAAE,sGAAsG;IACnH,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,sDAAsD;IACtE,QAAQ,EAAE;QACR,yBAAyB;QACzB,yHAAyH;QACzH,2BAA2B;QAC3B,6FAA6F;QAC7F,8BAA8B;QAC9B,sDAAsD;QACtD,+BAA+B;QAC/B,mDAAmD;QACnD,wBAAwB;QACxB,kDAAkD;KACnD;IACD,gBAAgB,EAAE;QAChB,qBAAqB;QACrB,cAAc;QACd,wBAAwB;QACxB,iBAAiB;KAClB;IACD,OAAO,EAAE,yFAAyF;IAClG,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAqB;IAC3D,EAAE,EAAE,oBAAoB;IACxB,IAAI,EAAE,wCAAwC;IAC9C,WAAW,EAAE,+DAA+D;IAC5E,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,mDAAmD;IACnE,QAAQ,EAAE;QACR,8BAA8B;QAC9B,mGAAmG;QACnG,kCAAkC;QAClC,mGAAmG;QACnG,wBAAwB;QACxB,kDAAkD;QAClD,8BAA8B;QAC9B,wFAAwF;QACxF,6BAA6B;QAC7B,uDAAuD;QACvD,gCAAgC;QAChC,iDAAiD;KAClD;IACD,gBAAgB,EAAE;QAChB,kBAAkB;QAClB,cAAc;QACd,WAAW;QACX,UAAU;KACX;IACD,OAAO,EAAE,+FAA+F;IACxG,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,YAAY;CACvB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAqB;IACxD,EAAE,EAAE,mBAAmB;IACvB,IAAI,EAAE,mCAAmC;IACzC,WAAW,EAAE,uEAAuE;IACpF,QAAQ,EAAE,MAAM;IAChB,cAAc,EAAE,yDAAyD;IACzE,QAAQ,EAAE;QACR,oCAAoC;QACpC,kFAAkF;QAClF,4CAA4C;QAC5C,+CAA+C;QAC/C,yBAAyB;QACzB,mCAAmC;QACnC,oCAAoC;QACpC,iCAAiC;QACjC,uBAAuB;QACvB,iDAAiD;KAClD;IACD,gBAAgB,EAAE;QAChB,0BAA0B,EAAE,qBAAqB;QACjD,0CAA0C;QAC1C,cAAc;KACf;IACD,OAAO,EAAE,+EAA+E;IACxF,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAqB;IAC1D,EAAE,EAAE,kBAAkB;IACtB,IAAI,EAAE,qCAAqC;IAC3C,WAAW,EAAE,wEAAwE;IACrF,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,kEAAkE;IAClF,QAAQ,EAAE;QACR,2CAA2C;QAC3C,8FAA8F;QAC9F,sCAAsC;QACtC,yEAAyE;QACzE,0BAA0B;QAC1B,6DAA6D;QAC7D,8BAA8B;QAC9B,sEAAsE;KACvE;IACD,gBAAgB,EAAE;QAChB,kBAAkB;QAClB,wBAAwB;QACxB,sBAAsB;QACtB,oBAAoB;KACrB;IACD,OAAO,EAAE,+FAA+F;IACxG,UAAU,EAAE,QAAQ;IACpB,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAqB;IAC5D,EAAE,EAAE,kBAAkB;IACtB,IAAI,EAAE,uCAAuC;IAC7C,WAAW,EAAE,wEAAwE;IACrF,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,qEAAqE;IACrF,QAAQ,EAAE;QACR,yCAAyC;QACzC,mHAAmH;QACnH,2CAA2C;QAC3C,qEAAqE;QACrE,oCAAoC;QACpC,kEAAkE;KACnE;IACD,gBAAgB,EAAE;QAChB,uBAAuB;QACvB,4BAA4B;QAC5B,sBAAsB;QACtB,eAAe;KAChB;IACD,OAAO,EAAE,0FAA0F;IACnG,UAAU,EAAE,QAAQ;IACpB,QAAQ,EAAE,eAAe;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAqB;IAC7D,EAAE,EAAE,mBAAmB;IACvB,IAAI,EAAE,sCAAsC;IAC5C,WAAW,EAAE,iFAAiF;IAC9F,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,0DAA0D;IAC1E,QAAQ,EAAE;QACR,oCAAoC;QACpC,+DAA+D;QAC/D,uCAAuC;QACvC,wEAAwE;QACxE,2CAA2C;QAC3C,6FAA6F;QAC7F,4BAA4B;QAC5B,4EAA4E;KAC7E;IACD,gBAAgB,EAAE;QAChB,oBAAoB,EAAE,YAAY;QAClC,mBAAmB;QACnB,gBAAgB;QAChB,mBAAmB;KACpB;IACD,OAAO,EAAE,gGAAgG;IACzG,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAqB;IACxD,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,0CAA0C;IAChD,WAAW,EAAE,+EAA+E;IAC5F,QAAQ,EAAE,MAAM;IAChB,cAAc,EAAE,yDAAyD;IACzE,QAAQ,EAAE;QACR,YAAY;QACZ,gEAAgE;QAChE,mBAAmB;QACnB,8BAA8B;QAC9B,2BAA2B;QAC3B,qDAAqD;QACrD,OAAO;QACP,gCAAgC;KACjC;IACD,OAAO,EAAE,gEAAgE;IACzE,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAqB;IACzD,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,4FAA4F;IACzG,QAAQ,EAAE,MAAM;IAChB,cAAc,EAAE,yDAAyD;IACzE,QAAQ,EAAE;QACR,eAAe;QACf,iEAAiE;QACjE,aAAa;QACb,mDAAmD;QACnD,UAAU;QACV,2CAA2C;QAC3C,SAAS;QACT,kDAAkD;KACnD;IACD,OAAO,EAAE,6DAA6D;IACtE,UAAU,EAAE,MAAM;IAClB,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAqB;IAC/D,EAAE,EAAE,mBAAmB;IACvB,IAAI,EAAE,8CAA8C;IACpD,WAAW,EAAE,gFAAgF;IAC7F,QAAQ,EAAE,MAAM;IAChB,cAAc,EAAE,+CAA+C;IAC/D,QAAQ,EAAE;QACR,oCAAoC;QACpC,mDAAmD;KACpD;IACD,gBAAgB,EAAE;QAChB,kBAAkB;QAClB,YAAY;QACZ,QAAQ;QACR,YAAY;QACZ,kBAAkB;KACnB;IACD,OAAO,EAAE,iFAAiF;IAC1F,UAAU,EAAE,QAAQ;IACpB,QAAQ,EAAE,eAAe;CAC1B,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAuB;IACzD,YAAY;IACZ,2BAA2B;IAC3B,wBAAwB;IACxB,0BAA0B;IAC1B,4BAA4B;IAC5B,6BAA6B;IAC7B,wBAAwB;IACxB,yBAAyB;IACzB,+BAA+B;CAChC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/operational/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAwB,MAAM,gBAAgB,CAAC;AAIpE,eAAO,MAAM,kBAAkB,EAAE,OA8GhC,CAAC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operational Security Scanner
|
|
3
|
+
* Detects database backup, data retention, and API security issues
|
|
4
|
+
*/
|
|
5
|
+
import { ALL_OPERATIONAL_PATTERNS, DATABASE_WITHOUT_BACKUP } from './patterns.js';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
export const operationalScanner = {
|
|
8
|
+
name: 'Operational Security Scanner',
|
|
9
|
+
category: 'data-retention',
|
|
10
|
+
async scan(files, options) {
|
|
11
|
+
const findings = [];
|
|
12
|
+
// Handle BACKUP-001 separately (requires project-wide scan)
|
|
13
|
+
const backupFinding = await scanForBackupConfiguration(files);
|
|
14
|
+
if (backupFinding) {
|
|
15
|
+
findings.push(backupFinding);
|
|
16
|
+
}
|
|
17
|
+
// Handle other patterns with line-by-line scanning
|
|
18
|
+
for (const file of files) {
|
|
19
|
+
// Skip non-code files
|
|
20
|
+
if (!file.match(/\.(ts|tsx|js|jsx|mjs|cjs)$/)) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
25
|
+
const lines = content.split('\n');
|
|
26
|
+
for (const pattern of ALL_OPERATIONAL_PATTERNS) {
|
|
27
|
+
// Skip BACKUP-001 (already handled)
|
|
28
|
+
if (pattern.id === 'BACKUP-001') {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
for (let i = 0; i < lines.length; i++) {
|
|
32
|
+
const line = lines[i];
|
|
33
|
+
// Skip comment lines
|
|
34
|
+
const trimmedLine = line.trim();
|
|
35
|
+
if (trimmedLine.startsWith('//') || trimmedLine.startsWith('/*') || trimmedLine.startsWith('*')) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// Check if line matches any positive pattern
|
|
39
|
+
const matched = pattern.patterns.some(p => p.test(line));
|
|
40
|
+
if (!matched)
|
|
41
|
+
continue;
|
|
42
|
+
// Get context for negative pattern checking
|
|
43
|
+
let contextLines;
|
|
44
|
+
if (pattern.id === 'RETENTION-001') {
|
|
45
|
+
// Check 15 lines of context for retention fields (larger object definition)
|
|
46
|
+
const start = Math.max(0, i - 5);
|
|
47
|
+
const end = Math.min(lines.length, i + 10);
|
|
48
|
+
contextLines = lines.slice(start, end);
|
|
49
|
+
}
|
|
50
|
+
else if (pattern.id === 'API-002') {
|
|
51
|
+
// Check 5 lines of context for limit configuration
|
|
52
|
+
const start = Math.max(0, i - 2);
|
|
53
|
+
const end = Math.min(lines.length, i + 3);
|
|
54
|
+
contextLines = lines.slice(start, end);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
contextLines = [line];
|
|
58
|
+
}
|
|
59
|
+
const context = contextLines.join('\n');
|
|
60
|
+
// Filter out comments from context
|
|
61
|
+
const contextWithoutComments = context
|
|
62
|
+
.split('\n')
|
|
63
|
+
.filter(l => {
|
|
64
|
+
const t = l.trim();
|
|
65
|
+
return !t.startsWith('//') && !t.startsWith('/*') && !t.startsWith('*');
|
|
66
|
+
})
|
|
67
|
+
.join('\n');
|
|
68
|
+
// Check negative patterns
|
|
69
|
+
if (pattern.negativePatterns) {
|
|
70
|
+
const hasNegativeMatch = pattern.negativePatterns.some(np => np.test(contextWithoutComments));
|
|
71
|
+
if (hasNegativeMatch) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Determine category based on pattern
|
|
76
|
+
let category = 'data-retention';
|
|
77
|
+
if (pattern.id === 'API-002') {
|
|
78
|
+
category = 'access-control';
|
|
79
|
+
}
|
|
80
|
+
findings.push({
|
|
81
|
+
id: pattern.id,
|
|
82
|
+
title: pattern.name,
|
|
83
|
+
description: `${pattern.description}\n\nCode: ${line.trim()}`,
|
|
84
|
+
severity: pattern.severity,
|
|
85
|
+
category: category,
|
|
86
|
+
file,
|
|
87
|
+
line: i + 1,
|
|
88
|
+
column: line.indexOf(line.trim()) + 1,
|
|
89
|
+
recommendation: pattern.recommendation,
|
|
90
|
+
hipaaReference: pattern.hipaaReference,
|
|
91
|
+
confidence: 'medium',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
// Skip files that can't be read
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return findings;
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Scan entire project for database usage and backup configuration
|
|
106
|
+
* Returns a finding if database is used but no backup configuration is found
|
|
107
|
+
*/
|
|
108
|
+
async function scanForBackupConfiguration(files) {
|
|
109
|
+
let hasDatabaseUsage = false;
|
|
110
|
+
let hasBackupConfig = false;
|
|
111
|
+
let firstDbFile = null;
|
|
112
|
+
let firstDbLine = 0;
|
|
113
|
+
let firstDbCode = '';
|
|
114
|
+
// Scan all files to detect database usage and backup configuration
|
|
115
|
+
for (const file of files) {
|
|
116
|
+
if (!file.match(/\.(ts|tsx|js|jsx|mjs|cjs|json|yml|yaml)$/)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
121
|
+
const lines = content.split('\n');
|
|
122
|
+
// Check for database usage
|
|
123
|
+
if (!hasDatabaseUsage) {
|
|
124
|
+
for (let i = 0; i < lines.length; i++) {
|
|
125
|
+
const line = lines[i];
|
|
126
|
+
const matched = DATABASE_WITHOUT_BACKUP.patterns.some(p => p.test(line));
|
|
127
|
+
if (matched) {
|
|
128
|
+
hasDatabaseUsage = true;
|
|
129
|
+
if (!firstDbFile) {
|
|
130
|
+
firstDbFile = file;
|
|
131
|
+
firstDbLine = i + 1;
|
|
132
|
+
firstDbCode = line.trim();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Check for backup configuration (negative patterns)
|
|
138
|
+
if (!hasBackupConfig && DATABASE_WITHOUT_BACKUP.negativePatterns) {
|
|
139
|
+
const hasBackup = DATABASE_WITHOUT_BACKUP.negativePatterns.some(np => np.test(content));
|
|
140
|
+
if (hasBackup) {
|
|
141
|
+
hasBackupConfig = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// If we found both, we can stop early
|
|
145
|
+
if (hasDatabaseUsage && hasBackupConfig) {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
// Skip files that can't be read
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// If database is used but no backup config found, create a finding
|
|
155
|
+
if (hasDatabaseUsage && !hasBackupConfig && firstDbFile) {
|
|
156
|
+
return {
|
|
157
|
+
id: DATABASE_WITHOUT_BACKUP.id,
|
|
158
|
+
title: DATABASE_WITHOUT_BACKUP.name,
|
|
159
|
+
description: `${DATABASE_WITHOUT_BACKUP.description}\n\nCode: ${firstDbCode}`,
|
|
160
|
+
severity: DATABASE_WITHOUT_BACKUP.severity,
|
|
161
|
+
category: 'data-retention',
|
|
162
|
+
file: firstDbFile,
|
|
163
|
+
line: firstDbLine,
|
|
164
|
+
recommendation: DATABASE_WITHOUT_BACKUP.recommendation,
|
|
165
|
+
hipaaReference: DATABASE_WITHOUT_BACKUP.hipaaReference,
|
|
166
|
+
confidence: 'low', // Low confidence since this is advisory
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/operational/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/scanners/operational/index.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|