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,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Factor Authentication (MFA) Detection Patterns
|
|
3
|
+
* Enforces MFA requirements per HIPAA NPRM §164.312(d)
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* MFA-001: Auth Provider Configuration Without MFA
|
|
7
|
+
* Detects NextAuth, Clerk, Auth0, Supabase Auth configs without MFA enabled
|
|
8
|
+
*/
|
|
9
|
+
export const AUTH_CONFIG_NO_MFA = {
|
|
10
|
+
id: 'MFA-001',
|
|
11
|
+
name: 'Authentication Configuration Without MFA Enabled',
|
|
12
|
+
description: 'Auth provider configuration (NextAuth, Clerk, Auth0, Supabase) does not have MFA/2FA/TOTP enabled',
|
|
13
|
+
severity: 'critical',
|
|
14
|
+
hipaaReference: 'NPRM §164.312(d) - Person or Entity Authentication',
|
|
15
|
+
patterns: [
|
|
16
|
+
// NextAuth configuration
|
|
17
|
+
/NextAuth\s*\(/i,
|
|
18
|
+
/export\s+(?:default\s+)?NextAuth/i,
|
|
19
|
+
/authOptions\s*[:=]/i,
|
|
20
|
+
// Clerk configuration
|
|
21
|
+
/ClerkProvider/i,
|
|
22
|
+
/clerk\.(?:setup|configure)/i,
|
|
23
|
+
// Auth0 configuration
|
|
24
|
+
/Auth0Provider/i,
|
|
25
|
+
/auth0\.WebAuth/i,
|
|
26
|
+
/new\s+Auth0Client/i,
|
|
27
|
+
// Supabase Auth configuration
|
|
28
|
+
/supabase\.auth\.signUp/i,
|
|
29
|
+
/createClient.*?supabase/i,
|
|
30
|
+
// Generic auth configs
|
|
31
|
+
/authConfig\s*[:=]/i,
|
|
32
|
+
/authentication\s*:\s*\{/i,
|
|
33
|
+
],
|
|
34
|
+
negativePatterns: [
|
|
35
|
+
// Indicators that MFA is enabled
|
|
36
|
+
/mfa/i,
|
|
37
|
+
/2fa/i,
|
|
38
|
+
/totp/i,
|
|
39
|
+
/otp/i,
|
|
40
|
+
/multiFactor/i,
|
|
41
|
+
/multi[-_]factor/i,
|
|
42
|
+
/twoFactor/i,
|
|
43
|
+
/two[-_]factor/i,
|
|
44
|
+
/authenticator/i,
|
|
45
|
+
],
|
|
46
|
+
recommendation: 'Enable MFA in your auth provider configuration. For NextAuth: add adapter with MFA support. For Clerk: enable MFA in dashboard. For Auth0: enable MFA in tenant settings. For Supabase: enable MFA in auth settings.',
|
|
47
|
+
category: 'authentication',
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* MFA-002: Login Flow Without Second Factor
|
|
51
|
+
* Detects signIn/login with only email+password without MFA verification
|
|
52
|
+
*/
|
|
53
|
+
export const LOGIN_NO_SECOND_FACTOR = {
|
|
54
|
+
id: 'MFA-002',
|
|
55
|
+
name: 'Login Flow Without Second Factor Authentication',
|
|
56
|
+
description: 'Login/sign-in flow authenticates with only email and password without requiring second factor verification',
|
|
57
|
+
severity: 'high',
|
|
58
|
+
hipaaReference: 'NPRM §164.312(d) - Person or Entity Authentication',
|
|
59
|
+
patterns: [
|
|
60
|
+
// signIn with email+password
|
|
61
|
+
/(?:signIn|login|authenticate)\s*\([^)]*(?:email|username)[^)]*password/i,
|
|
62
|
+
/(?:signIn|login|authenticate)\s*\(\s*\{[^}]*(?:email|username)[^}]*password[^}]*\}/i,
|
|
63
|
+
// Credentials-based auth without MFA
|
|
64
|
+
/credentials\s*:\s*\{[^}]*(?:email|username)[^}]*password[^}]*\}/i,
|
|
65
|
+
// Direct password authentication
|
|
66
|
+
/(?:email|username)\s*,\s*password\s*\)/i,
|
|
67
|
+
/password\s*,\s*(?:email|username)\s*\)/i,
|
|
68
|
+
],
|
|
69
|
+
negativePatterns: [
|
|
70
|
+
// Indicators of MFA verification
|
|
71
|
+
/mfaToken/i,
|
|
72
|
+
/totpCode/i,
|
|
73
|
+
/verificationCode/i,
|
|
74
|
+
/twoFactorCode/i,
|
|
75
|
+
/authenticatorCode/i,
|
|
76
|
+
/otp/i,
|
|
77
|
+
/mfaVerified/i,
|
|
78
|
+
/requireMfa/i,
|
|
79
|
+
/checkMfa/i,
|
|
80
|
+
/verifyMfa/i,
|
|
81
|
+
],
|
|
82
|
+
recommendation: 'Add second factor verification to login flow. After successful password authentication, require MFA token/TOTP code before granting access. Example: if (user.mfaEnabled && !mfaToken) return { error: "MFA required" }',
|
|
83
|
+
category: 'authentication',
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* MFA-003: MFA Bypass in Code
|
|
87
|
+
* Detects code that explicitly bypasses or disables MFA requirements
|
|
88
|
+
*/
|
|
89
|
+
export const MFA_BYPASS = {
|
|
90
|
+
id: 'MFA-003',
|
|
91
|
+
name: 'MFA Bypass Detected in Code',
|
|
92
|
+
description: 'Code explicitly bypasses, skips, or disables MFA requirements',
|
|
93
|
+
severity: 'critical',
|
|
94
|
+
hipaaReference: 'NPRM §164.312(d) - Person or Entity Authentication',
|
|
95
|
+
patterns: [
|
|
96
|
+
// Explicit bypass functions
|
|
97
|
+
/skipMfa/i,
|
|
98
|
+
/bypassMfa/i,
|
|
99
|
+
/disableMfa/i,
|
|
100
|
+
/ignoreMfa/i,
|
|
101
|
+
// MFA disabled in config
|
|
102
|
+
/mfaEnabled\s*[:=]\s*false/i,
|
|
103
|
+
/requireMfa\s*[:=]\s*false/i,
|
|
104
|
+
/require(?:Two|2)Factor\s*[:=]\s*false/i,
|
|
105
|
+
/mfa\s*:\s*\{\s*enabled\s*:\s*false/i,
|
|
106
|
+
/twoFactor\s*:\s*false/i,
|
|
107
|
+
// Conditional bypass
|
|
108
|
+
/if\s*\([^)]*skip.*mfa/i,
|
|
109
|
+
/if\s*\([^)]*!.*(?:mfa|2fa|totp)/i,
|
|
110
|
+
// Environment-based bypass (common anti-pattern)
|
|
111
|
+
/process\.env\.(?:SKIP|DISABLE|BYPASS).*MFA/i,
|
|
112
|
+
],
|
|
113
|
+
negativePatterns: [
|
|
114
|
+
// Valid use cases (testing, error messages)
|
|
115
|
+
/\/\/.*test/i,
|
|
116
|
+
/\/\*.*test/i,
|
|
117
|
+
/describe\(/i,
|
|
118
|
+
/it\(/i,
|
|
119
|
+
/test\(/i,
|
|
120
|
+
/\.test\./i,
|
|
121
|
+
/\.spec\./i,
|
|
122
|
+
/console\.(?:log|warn|error)/i,
|
|
123
|
+
/throw.*error/i,
|
|
124
|
+
],
|
|
125
|
+
recommendation: 'Remove MFA bypass code. MFA should be mandatory for all users accessing PHI. If testing is needed, use proper test isolation instead of disabling MFA in production code.',
|
|
126
|
+
category: 'authentication',
|
|
127
|
+
};
|
|
128
|
+
export const ALL_MFA_PATTERNS = [
|
|
129
|
+
AUTH_CONFIG_NO_MFA,
|
|
130
|
+
LOGIN_NO_SECOND_FACTOR,
|
|
131
|
+
MFA_BYPASS,
|
|
132
|
+
];
|
|
133
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/scanners/authentication/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAe;IAC5C,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,kDAAkD;IACxD,WAAW,EACT,mGAAmG;IACrG,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,oDAAoD;IACpE,QAAQ,EAAE;QACR,yBAAyB;QACzB,gBAAgB;QAChB,mCAAmC;QACnC,qBAAqB;QAErB,sBAAsB;QACtB,gBAAgB;QAChB,6BAA6B;QAE7B,sBAAsB;QACtB,gBAAgB;QAChB,iBAAiB;QACjB,oBAAoB;QAEpB,8BAA8B;QAC9B,yBAAyB;QACzB,0BAA0B;QAE1B,uBAAuB;QACvB,oBAAoB;QACpB,0BAA0B;KAC3B;IACD,gBAAgB,EAAE;QAChB,iCAAiC;QACjC,MAAM;QACN,MAAM;QACN,OAAO;QACP,MAAM;QACN,cAAc;QACd,kBAAkB;QAClB,YAAY;QACZ,gBAAgB;QAChB,gBAAgB;KACjB;IACD,cAAc,EACZ,sNAAsN;IACxN,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAe;IAChD,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,iDAAiD;IACvD,WAAW,EACT,4GAA4G;IAC9G,QAAQ,EAAE,MAAM;IAChB,cAAc,EAAE,oDAAoD;IACpE,QAAQ,EAAE;QACR,6BAA6B;QAC7B,yEAAyE;QACzE,qFAAqF;QAErF,qCAAqC;QACrC,kEAAkE;QAElE,iCAAiC;QACjC,yCAAyC;QACzC,yCAAyC;KAC1C;IACD,gBAAgB,EAAE;QAChB,iCAAiC;QACjC,WAAW;QACX,WAAW;QACX,mBAAmB;QACnB,gBAAgB;QAChB,oBAAoB;QACpB,MAAM;QACN,cAAc;QACd,aAAa;QACb,WAAW;QACX,YAAY;KACb;IACD,cAAc,EACZ,yNAAyN;IAC3N,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAe;IACpC,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,6BAA6B;IACnC,WAAW,EACT,+DAA+D;IACjE,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,oDAAoD;IACpE,QAAQ,EAAE;QACR,4BAA4B;QAC5B,UAAU;QACV,YAAY;QACZ,aAAa;QACb,YAAY;QAEZ,yBAAyB;QACzB,4BAA4B;QAC5B,4BAA4B;QAC5B,wCAAwC;QACxC,qCAAqC;QACrC,wBAAwB;QAExB,qBAAqB;QACrB,wBAAwB;QACxB,kCAAkC;QAElC,iDAAiD;QACjD,6CAA6C;KAC9C;IACD,gBAAgB,EAAE;QAChB,4CAA4C;QAC5C,aAAa;QACb,aAAa;QACb,aAAa;QACb,OAAO;QACP,SAAS;QACT,WAAW;QACX,WAAW;QACX,8BAA8B;QAC9B,eAAe;KAChB;IACD,cAAc,EACZ,2KAA2K;IAC7K,QAAQ,EAAE,gBAAgB;CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,kBAAkB;IAClB,sBAAsB;IACtB,UAAU;CACX,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Security Scanner
|
|
3
|
+
* Detects insecure configuration settings and missing security controls
|
|
4
|
+
*/
|
|
5
|
+
import type { Scanner } from '../../types.js';
|
|
6
|
+
export declare const configurationScanner: Scanner;
|
|
7
|
+
export default configurationScanner;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/configuration/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAwB,MAAM,gBAAgB,CAAC;AAGpE,eAAO,MAAM,oBAAoB,EAAE,OA8FlC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Security Scanner
|
|
3
|
+
* Detects insecure configuration settings and missing security controls
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import { ALL_CONFIGURATION_PATTERNS } from './patterns.js';
|
|
7
|
+
export const configurationScanner = {
|
|
8
|
+
name: 'Configuration Security Scanner',
|
|
9
|
+
category: 'audit-logging',
|
|
10
|
+
async scan(files, options) {
|
|
11
|
+
const findings = [];
|
|
12
|
+
// Filter to code files
|
|
13
|
+
const codeFiles = files.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f));
|
|
14
|
+
for (const file of codeFiles) {
|
|
15
|
+
try {
|
|
16
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
17
|
+
const lines = content.split('\n');
|
|
18
|
+
// Check if this is a test file for CONFIG-003
|
|
19
|
+
const isTestFile = /\.(?:test|spec)\.[jt]sx?$/.test(file);
|
|
20
|
+
for (let i = 0; i < lines.length; i++) {
|
|
21
|
+
const line = lines[i];
|
|
22
|
+
const lineNumber = i + 1;
|
|
23
|
+
// Skip empty lines and full-line comments
|
|
24
|
+
if (/^\s*$/.test(line) || /^\s*\/\//.test(line))
|
|
25
|
+
continue;
|
|
26
|
+
// Scan each pattern
|
|
27
|
+
for (const pattern of ALL_CONFIGURATION_PATTERNS) {
|
|
28
|
+
// CONFIG-003: Skip test files entirely
|
|
29
|
+
if (pattern.id === 'CONFIG-003' && isTestFile)
|
|
30
|
+
continue;
|
|
31
|
+
// Check if line matches violation pattern
|
|
32
|
+
const matched = pattern.patterns.some((regex) => regex.test(line));
|
|
33
|
+
if (!matched)
|
|
34
|
+
continue;
|
|
35
|
+
// Get surrounding context
|
|
36
|
+
const contextBefore = pattern.id === 'CONFIG-001' ? 5 :
|
|
37
|
+
pattern.id === 'CONFIG-002' ? 20 : 0;
|
|
38
|
+
const contextAfter = pattern.id === 'CONFIG-001' ? 5 :
|
|
39
|
+
pattern.id === 'CONFIG-002' ? 10 : 0;
|
|
40
|
+
const contextStart = Math.max(0, i - contextBefore);
|
|
41
|
+
const contextEnd = Math.min(lines.length, i + contextAfter + 1);
|
|
42
|
+
const contextLines = lines.slice(contextStart, contextEnd);
|
|
43
|
+
// Filter out comment lines from context
|
|
44
|
+
const codeOnlyContext = contextLines
|
|
45
|
+
.filter(l => !/^\s*\/\//.test(l) && !/^\s*\/\*/.test(l) && !/^\s*\*/.test(l))
|
|
46
|
+
.join('\n');
|
|
47
|
+
// Check negative patterns (safe usage indicators)
|
|
48
|
+
const isSafe = pattern.negativePatterns?.some((regex) => {
|
|
49
|
+
// For CONFIG-001, check if there's NODE_ENV gate in context
|
|
50
|
+
if (pattern.id === 'CONFIG-001') {
|
|
51
|
+
return regex.test(codeOnlyContext);
|
|
52
|
+
}
|
|
53
|
+
// For CONFIG-002, check if security headers are set in context
|
|
54
|
+
if (pattern.id === 'CONFIG-002') {
|
|
55
|
+
return regex.test(codeOnlyContext);
|
|
56
|
+
}
|
|
57
|
+
// For CONFIG-003, no negative patterns to check (handled by filename)
|
|
58
|
+
return false;
|
|
59
|
+
});
|
|
60
|
+
if (isSafe)
|
|
61
|
+
continue;
|
|
62
|
+
// Create finding
|
|
63
|
+
const finding = {
|
|
64
|
+
id: pattern.id,
|
|
65
|
+
category: pattern.category,
|
|
66
|
+
severity: pattern.severity,
|
|
67
|
+
title: pattern.name,
|
|
68
|
+
description: `${pattern.description}\n\nCode: ${line.trim()}`,
|
|
69
|
+
file: file,
|
|
70
|
+
line: lineNumber,
|
|
71
|
+
recommendation: pattern.recommendation,
|
|
72
|
+
hipaaReference: pattern.hipaaReference,
|
|
73
|
+
confidence: 'high',
|
|
74
|
+
};
|
|
75
|
+
findings.push(finding);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
// Skip files that can't be read
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return findings;
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
export default configurationScanner;
|
|
87
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/configuration/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/scanners/configuration/index.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Security Scanner Tests
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
5
|
+
import { configurationScanner } from './index.js';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import * as os from 'os';
|
|
9
|
+
describe('Configuration Security Scanner', () => {
|
|
10
|
+
let tempDir = '';
|
|
11
|
+
let testFiles = [];
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'config-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('CONFIG-001: Debug/Verbose Mode Without Environment Gate', () => {
|
|
43
|
+
it('should detect debug:true without NODE_ENV gate', async () => {
|
|
44
|
+
const file = await createTestFile('config.ts', `export const config = {
|
|
45
|
+
debug: true,
|
|
46
|
+
apiUrl: 'https://api.example.com'
|
|
47
|
+
};`);
|
|
48
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
49
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-001');
|
|
50
|
+
expect(configFindings.length).toBeGreaterThan(0);
|
|
51
|
+
expect(configFindings[0].severity).toBe('high');
|
|
52
|
+
});
|
|
53
|
+
it('should detect DEBUG:true', async () => {
|
|
54
|
+
const file = await createTestFile('env.ts', `
|
|
55
|
+
const settings = {
|
|
56
|
+
DEBUG: true,
|
|
57
|
+
port: 3000
|
|
58
|
+
};
|
|
59
|
+
`);
|
|
60
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
61
|
+
expect(findings.some((f) => f.id === 'CONFIG-001')).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
it('should detect verbose:true', async () => {
|
|
64
|
+
const file = await createTestFile('logger.ts', `
|
|
65
|
+
const loggerConfig = {
|
|
66
|
+
verbose: true,
|
|
67
|
+
level: 'info'
|
|
68
|
+
};
|
|
69
|
+
`);
|
|
70
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
71
|
+
expect(findings.some((f) => f.id === 'CONFIG-001')).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
it('should detect devTools:true', async () => {
|
|
74
|
+
const file = await createTestFile('redux.ts', `
|
|
75
|
+
const store = createStore(reducer, {
|
|
76
|
+
devTools: true
|
|
77
|
+
});
|
|
78
|
+
`);
|
|
79
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
80
|
+
expect(findings.some((f) => f.id === 'CONFIG-001')).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
it('should NOT flag debug with NODE_ENV gate', async () => {
|
|
83
|
+
const file = await createTestFile('safe-config.ts', `
|
|
84
|
+
export const config = {
|
|
85
|
+
debug: process.env.NODE_ENV === 'development',
|
|
86
|
+
apiUrl: 'https://api.example.com'
|
|
87
|
+
};
|
|
88
|
+
`);
|
|
89
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
90
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-001');
|
|
91
|
+
expect(configFindings.length).toBe(0);
|
|
92
|
+
});
|
|
93
|
+
it('should NOT flag debug with isDevelopment check', async () => {
|
|
94
|
+
const file = await createTestFile('safe-debug.ts', `
|
|
95
|
+
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
96
|
+
export const config = {
|
|
97
|
+
debug: isDevelopment
|
|
98
|
+
};
|
|
99
|
+
`);
|
|
100
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
101
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-001');
|
|
102
|
+
expect(configFindings.length).toBe(0);
|
|
103
|
+
});
|
|
104
|
+
it('should NOT flag debug in test files', async () => {
|
|
105
|
+
const file = await createTestFile('app.test.ts', `
|
|
106
|
+
describe('app', () => {
|
|
107
|
+
const config = { debug: true };
|
|
108
|
+
it('should work', () => {});
|
|
109
|
+
});
|
|
110
|
+
`);
|
|
111
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
112
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-001');
|
|
113
|
+
expect(configFindings.length).toBe(0);
|
|
114
|
+
});
|
|
115
|
+
it('should NOT flag debug in conditional', async () => {
|
|
116
|
+
const file = await createTestFile('conditional.ts', `
|
|
117
|
+
const config = {
|
|
118
|
+
debug: process.env.NODE_ENV !== 'production'
|
|
119
|
+
};
|
|
120
|
+
`);
|
|
121
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
122
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-001');
|
|
123
|
+
expect(configFindings.length).toBe(0);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('CONFIG-002: Web Server Without Security Headers', () => {
|
|
127
|
+
it('should detect express() without helmet', async () => {
|
|
128
|
+
const file = await createTestFile('server.ts', `
|
|
129
|
+
import express from 'express';
|
|
130
|
+
|
|
131
|
+
const app = express();
|
|
132
|
+
|
|
133
|
+
app.get('/', (req, res) => {
|
|
134
|
+
res.send('Hello');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
app.listen(3000);
|
|
138
|
+
`);
|
|
139
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
140
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-002');
|
|
141
|
+
expect(configFindings.length).toBeGreaterThan(0);
|
|
142
|
+
expect(configFindings[0].severity).toBe('medium');
|
|
143
|
+
});
|
|
144
|
+
it('should detect http.createServer without headers', async () => {
|
|
145
|
+
const file = await createTestFile('http-server.ts', `
|
|
146
|
+
import http from 'http';
|
|
147
|
+
|
|
148
|
+
const server = http.createServer((req, res) => {
|
|
149
|
+
res.end('Hello');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
server.listen(3000);
|
|
153
|
+
`);
|
|
154
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
155
|
+
expect(findings.some((f) => f.id === 'CONFIG-002')).toBe(true);
|
|
156
|
+
});
|
|
157
|
+
it('should detect new Hono() without security', async () => {
|
|
158
|
+
const file = await createTestFile('hono-app.ts', `
|
|
159
|
+
import { Hono } from 'hono';
|
|
160
|
+
|
|
161
|
+
const app = new Hono();
|
|
162
|
+
|
|
163
|
+
app.get('/', (c) => c.text('Hello'));
|
|
164
|
+
`);
|
|
165
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
166
|
+
expect(findings.some((f) => f.id === 'CONFIG-002')).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
it('should detect new Elysia() without security', async () => {
|
|
169
|
+
const file = await createTestFile('elysia-app.ts', `
|
|
170
|
+
import { Elysia } from 'elysia';
|
|
171
|
+
|
|
172
|
+
const app = new Elysia();
|
|
173
|
+
`);
|
|
174
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
175
|
+
expect(findings.some((f) => f.id === 'CONFIG-002')).toBe(true);
|
|
176
|
+
});
|
|
177
|
+
it('should NOT flag express with helmet', async () => {
|
|
178
|
+
const file = await createTestFile('secure-express.ts', `
|
|
179
|
+
import express from 'express';
|
|
180
|
+
import helmet from 'helmet';
|
|
181
|
+
|
|
182
|
+
const app = express();
|
|
183
|
+
app.use(helmet());
|
|
184
|
+
|
|
185
|
+
app.listen(3000);
|
|
186
|
+
`);
|
|
187
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
188
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-002');
|
|
189
|
+
expect(configFindings.length).toBe(0);
|
|
190
|
+
});
|
|
191
|
+
it('should NOT flag server with X-Frame-Options header', async () => {
|
|
192
|
+
const file = await createTestFile('secure-headers.ts', `
|
|
193
|
+
const app = express();
|
|
194
|
+
|
|
195
|
+
app.use((req, res, next) => {
|
|
196
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
197
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
198
|
+
next();
|
|
199
|
+
});
|
|
200
|
+
`);
|
|
201
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
202
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-002');
|
|
203
|
+
expect(configFindings.length).toBe(0);
|
|
204
|
+
});
|
|
205
|
+
it('should NOT flag server with CSP header', async () => {
|
|
206
|
+
const file = await createTestFile('csp-headers.ts', `
|
|
207
|
+
import http from 'http';
|
|
208
|
+
|
|
209
|
+
const server = http.createServer((req, res) => {
|
|
210
|
+
res.setHeader('Content-Security-Policy', "default-src 'self'");
|
|
211
|
+
res.end('Hello');
|
|
212
|
+
});
|
|
213
|
+
`);
|
|
214
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
215
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-002');
|
|
216
|
+
expect(configFindings.length).toBe(0);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
describe('CONFIG-003: Test Framework Imports in Production Code', () => {
|
|
220
|
+
it('should detect jest import in production file', async () => {
|
|
221
|
+
const file = await createTestFile('utils.ts', `
|
|
222
|
+
import { jest } from '@jest/globals';
|
|
223
|
+
|
|
224
|
+
export function mockFunction() {
|
|
225
|
+
return jest.fn();
|
|
226
|
+
}
|
|
227
|
+
`);
|
|
228
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
229
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-003');
|
|
230
|
+
expect(configFindings.length).toBeGreaterThan(0);
|
|
231
|
+
expect(configFindings[0].severity).toBe('low');
|
|
232
|
+
});
|
|
233
|
+
it('should detect vitest import in production file', async () => {
|
|
234
|
+
const file = await createTestFile('helper.ts', `
|
|
235
|
+
import { describe, it, expect } from 'vitest';
|
|
236
|
+
|
|
237
|
+
export function runTests() {
|
|
238
|
+
describe('tests', () => {});
|
|
239
|
+
}
|
|
240
|
+
`);
|
|
241
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
242
|
+
expect(findings.some((f) => f.id === 'CONFIG-003')).toBe(true);
|
|
243
|
+
});
|
|
244
|
+
it('should detect mocha import in production file', async () => {
|
|
245
|
+
const file = await createTestFile('runner.ts', `
|
|
246
|
+
import { describe } from 'mocha';
|
|
247
|
+
`);
|
|
248
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
249
|
+
expect(findings.some((f) => f.id === 'CONFIG-003')).toBe(true);
|
|
250
|
+
});
|
|
251
|
+
it('should detect chai import in production file', async () => {
|
|
252
|
+
const file = await createTestFile('assertions.ts', `
|
|
253
|
+
import { expect } from 'chai';
|
|
254
|
+
`);
|
|
255
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
256
|
+
expect(findings.some((f) => f.id === 'CONFIG-003')).toBe(true);
|
|
257
|
+
});
|
|
258
|
+
it('should detect faker import in production file', async () => {
|
|
259
|
+
const file = await createTestFile('data.ts', `
|
|
260
|
+
import { faker } from '@faker-js/faker';
|
|
261
|
+
|
|
262
|
+
export const fakeData = faker.name.firstName();
|
|
263
|
+
`);
|
|
264
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
265
|
+
expect(findings.some((f) => f.id === 'CONFIG-003')).toBe(true);
|
|
266
|
+
});
|
|
267
|
+
it('should detect cypress import in production file', async () => {
|
|
268
|
+
const file = await createTestFile('commands.ts', `
|
|
269
|
+
import { cy } from 'cypress';
|
|
270
|
+
`);
|
|
271
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
272
|
+
expect(findings.some((f) => f.id === 'CONFIG-003')).toBe(true);
|
|
273
|
+
});
|
|
274
|
+
it('should NOT flag test framework imports in test files', async () => {
|
|
275
|
+
const file = await createTestFile('app.test.ts', `
|
|
276
|
+
import { describe, it, expect } from 'vitest';
|
|
277
|
+
import { jest } from '@jest/globals';
|
|
278
|
+
|
|
279
|
+
describe('app', () => {
|
|
280
|
+
it('should work', () => {
|
|
281
|
+
expect(true).toBe(true);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
`);
|
|
285
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
286
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-003');
|
|
287
|
+
expect(configFindings.length).toBe(0);
|
|
288
|
+
});
|
|
289
|
+
it('should NOT flag test framework imports in spec files', async () => {
|
|
290
|
+
const file = await createTestFile('component.spec.ts', `
|
|
291
|
+
import { describe, it } from 'mocha';
|
|
292
|
+
import { expect } from 'chai';
|
|
293
|
+
`);
|
|
294
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
295
|
+
const configFindings = findings.filter((f) => f.id === 'CONFIG-003');
|
|
296
|
+
expect(configFindings.length).toBe(0);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
describe('Combined violations', () => {
|
|
300
|
+
it('should detect multiple CONFIG violations in same file', async () => {
|
|
301
|
+
const file = await createTestFile('bad-config.ts', `
|
|
302
|
+
import { jest } from '@jest/globals';
|
|
303
|
+
import express from 'express';
|
|
304
|
+
|
|
305
|
+
const config = {
|
|
306
|
+
debug: true,
|
|
307
|
+
verbose: true
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const app = express();
|
|
311
|
+
|
|
312
|
+
app.listen(3000);
|
|
313
|
+
`);
|
|
314
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
315
|
+
expect(findings.some((f) => f.id === 'CONFIG-001')).toBe(true);
|
|
316
|
+
expect(findings.some((f) => f.id === 'CONFIG-002')).toBe(true);
|
|
317
|
+
expect(findings.some((f) => f.id === 'CONFIG-003')).toBe(true);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
it('should provide correct HIPAA references', async () => {
|
|
321
|
+
const file = await createTestFile('hipaa-refs.ts', `
|
|
322
|
+
const config = { debug: true };
|
|
323
|
+
const app = express();
|
|
324
|
+
import { vitest } from 'vitest';
|
|
325
|
+
`);
|
|
326
|
+
const findings = await configurationScanner.scan([file], scanOptions);
|
|
327
|
+
expect(findings.every((f) => f.hipaaReference?.includes('Configuration Management'))).toBe(true);
|
|
328
|
+
});
|
|
329
|
+
it('should have correct severity levels', async () => {
|
|
330
|
+
const file1 = await createTestFile('severity-high.ts', `const config = { debug: true };`);
|
|
331
|
+
const file2 = await createTestFile('severity-medium.ts', `const app = express();`);
|
|
332
|
+
const file3 = await createTestFile('severity-low.ts', `import { jest } from '@jest/globals';`);
|
|
333
|
+
const findings1 = await configurationScanner.scan([file1], scanOptions);
|
|
334
|
+
const findings2 = await configurationScanner.scan([file2], scanOptions);
|
|
335
|
+
const findings3 = await configurationScanner.scan([file3], scanOptions);
|
|
336
|
+
const config001 = findings1.find((f) => f.id === 'CONFIG-001');
|
|
337
|
+
const config002 = findings2.find((f) => f.id === 'CONFIG-002');
|
|
338
|
+
const config003 = findings3.find((f) => f.id === 'CONFIG-003');
|
|
339
|
+
expect(config001?.severity).toBe('high');
|
|
340
|
+
expect(config002?.severity).toBe('medium');
|
|
341
|
+
expect(config003?.severity).toBe('low');
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/scanners/configuration/index.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Security Detection Patterns
|
|
3
|
+
* Detects insecure configuration settings and missing security controls
|
|
4
|
+
*/
|
|
5
|
+
export interface ConfigurationPattern {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
severity: 'high' | 'medium' | 'low';
|
|
10
|
+
hipaaReference: string;
|
|
11
|
+
patterns: RegExp[];
|
|
12
|
+
negativePatterns?: RegExp[];
|
|
13
|
+
recommendation: string;
|
|
14
|
+
category: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* CONFIG-001: Debug/Verbose Mode Without Environment Gate
|
|
18
|
+
* Detects debug/verbose flags enabled without NODE_ENV check
|
|
19
|
+
*/
|
|
20
|
+
export declare const DEBUG_WITHOUT_ENV_GATE: ConfigurationPattern;
|
|
21
|
+
/**
|
|
22
|
+
* CONFIG-002: Web Server Without Security Headers
|
|
23
|
+
* Detects web servers created without helmet or security headers middleware
|
|
24
|
+
*/
|
|
25
|
+
export declare const SERVER_WITHOUT_SECURITY_HEADERS: ConfigurationPattern;
|
|
26
|
+
/**
|
|
27
|
+
* CONFIG-003: Test Framework Imports in Production Code
|
|
28
|
+
* Detects test framework imports in non-test files
|
|
29
|
+
*/
|
|
30
|
+
export declare const TEST_IMPORTS_IN_PRODUCTION: ConfigurationPattern;
|
|
31
|
+
export declare const ALL_CONFIGURATION_PATTERNS: ConfigurationPattern[];
|
|
32
|
+
//# sourceMappingURL=patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../../src/scanners/configuration/patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpC,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,sBAAsB,EAAE,oBAwDpC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,+BAA+B,EAAE,oBAqD7C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,oBA0CxC,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,oBAAoB,EAI5D,CAAC"}
|