verification-layer 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +251 -615
  2. package/dist/cli.js +283 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/reporters/audit-report.d.ts.map +1 -1
  5. package/dist/reporters/audit-report.js +180 -0
  6. package/dist/reporters/audit-report.js.map +1 -1
  7. package/dist/reporters/index.d.ts.map +1 -1
  8. package/dist/reporters/index.js +2612 -5
  9. package/dist/reporters/index.js.map +1 -1
  10. package/dist/scan.d.ts.map +1 -1
  11. package/dist/scan.js +14 -1
  12. package/dist/scan.js.map +1 -1
  13. package/dist/scanners/api-security/index.d.ts +7 -0
  14. package/dist/scanners/api-security/index.d.ts.map +1 -0
  15. package/dist/scanners/api-security/index.js +139 -0
  16. package/dist/scanners/api-security/index.js.map +1 -0
  17. package/dist/scanners/api-security/index.test.d.ts +5 -0
  18. package/dist/scanners/api-security/index.test.d.ts.map +1 -0
  19. package/dist/scanners/api-security/index.test.js +360 -0
  20. package/dist/scanners/api-security/index.test.js.map +1 -0
  21. package/dist/scanners/api-security/patterns.d.ts +32 -0
  22. package/dist/scanners/api-security/patterns.d.ts.map +1 -0
  23. package/dist/scanners/api-security/patterns.js +159 -0
  24. package/dist/scanners/api-security/patterns.js.map +1 -0
  25. package/dist/scanners/authentication/index.d.ts +7 -0
  26. package/dist/scanners/authentication/index.d.ts.map +1 -0
  27. package/dist/scanners/authentication/index.js +107 -0
  28. package/dist/scanners/authentication/index.js.map +1 -0
  29. package/dist/scanners/authentication/index.test.d.ts +5 -0
  30. package/dist/scanners/authentication/index.test.d.ts.map +1 -0
  31. package/dist/scanners/authentication/index.test.js +379 -0
  32. package/dist/scanners/authentication/index.test.js.map +1 -0
  33. package/dist/scanners/authentication/patterns.d.ts +32 -0
  34. package/dist/scanners/authentication/patterns.d.ts.map +1 -0
  35. package/dist/scanners/authentication/patterns.js +133 -0
  36. package/dist/scanners/authentication/patterns.js.map +1 -0
  37. package/dist/scanners/configuration/index.d.ts +8 -0
  38. package/dist/scanners/configuration/index.d.ts.map +1 -0
  39. package/dist/scanners/configuration/index.js +87 -0
  40. package/dist/scanners/configuration/index.js.map +1 -0
  41. package/dist/scanners/configuration/index.test.d.ts +5 -0
  42. package/dist/scanners/configuration/index.test.d.ts.map +1 -0
  43. package/dist/scanners/configuration/index.test.js +344 -0
  44. package/dist/scanners/configuration/index.test.js.map +1 -0
  45. package/dist/scanners/configuration/patterns.d.ts +32 -0
  46. package/dist/scanners/configuration/patterns.d.ts.map +1 -0
  47. package/dist/scanners/configuration/patterns.js +146 -0
  48. package/dist/scanners/configuration/patterns.js.map +1 -0
  49. package/dist/scanners/credentials/index.d.ts +7 -0
  50. package/dist/scanners/credentials/index.d.ts.map +1 -0
  51. package/dist/scanners/credentials/index.js +129 -0
  52. package/dist/scanners/credentials/index.js.map +1 -0
  53. package/dist/scanners/credentials/index.test.d.ts +5 -0
  54. package/dist/scanners/credentials/index.test.d.ts.map +1 -0
  55. package/dist/scanners/credentials/index.test.js +395 -0
  56. package/dist/scanners/credentials/index.test.js.map +1 -0
  57. package/dist/scanners/credentials/patterns.d.ts +32 -0
  58. package/dist/scanners/credentials/patterns.d.ts.map +1 -0
  59. package/dist/scanners/credentials/patterns.js +140 -0
  60. package/dist/scanners/credentials/patterns.js.map +1 -0
  61. package/dist/scanners/errors/index.d.ts +8 -0
  62. package/dist/scanners/errors/index.d.ts.map +1 -0
  63. package/dist/scanners/errors/index.js +78 -0
  64. package/dist/scanners/errors/index.js.map +1 -0
  65. package/dist/scanners/errors/index.test.d.ts +5 -0
  66. package/dist/scanners/errors/index.test.d.ts.map +1 -0
  67. package/dist/scanners/errors/index.test.js +330 -0
  68. package/dist/scanners/errors/index.test.js.map +1 -0
  69. package/dist/scanners/errors/patterns.d.ts +27 -0
  70. package/dist/scanners/errors/patterns.d.ts.map +1 -0
  71. package/dist/scanners/errors/patterns.js +97 -0
  72. package/dist/scanners/errors/patterns.js.map +1 -0
  73. package/dist/scanners/hipaa2026/index.d.ts.map +1 -1
  74. package/dist/scanners/hipaa2026/index.js +49 -17
  75. package/dist/scanners/hipaa2026/index.js.map +1 -1
  76. package/dist/scanners/hipaa2026/index.test.js +26 -15
  77. package/dist/scanners/hipaa2026/index.test.js.map +1 -1
  78. package/dist/scanners/operational/index.d.ts +7 -0
  79. package/dist/scanners/operational/index.d.ts.map +1 -0
  80. package/dist/scanners/operational/index.js +171 -0
  81. package/dist/scanners/operational/index.js.map +1 -0
  82. package/dist/scanners/operational/index.test.d.ts +5 -0
  83. package/dist/scanners/operational/index.test.d.ts.map +1 -0
  84. package/dist/scanners/operational/index.test.js +406 -0
  85. package/dist/scanners/operational/index.test.js.map +1 -0
  86. package/dist/scanners/operational/patterns.d.ts +33 -0
  87. package/dist/scanners/operational/patterns.d.ts.map +1 -0
  88. package/dist/scanners/operational/patterns.js +151 -0
  89. package/dist/scanners/operational/patterns.js.map +1 -0
  90. package/dist/scanners/rbac/index.d.ts +7 -0
  91. package/dist/scanners/rbac/index.d.ts.map +1 -0
  92. package/dist/scanners/rbac/index.js +145 -0
  93. package/dist/scanners/rbac/index.js.map +1 -0
  94. package/dist/scanners/rbac/index.test.d.ts +5 -0
  95. package/dist/scanners/rbac/index.test.d.ts.map +1 -0
  96. package/dist/scanners/rbac/index.test.js +422 -0
  97. package/dist/scanners/rbac/index.test.js.map +1 -0
  98. package/dist/scanners/rbac/patterns.d.ts +32 -0
  99. package/dist/scanners/rbac/patterns.d.ts.map +1 -0
  100. package/dist/scanners/rbac/patterns.js +124 -0
  101. package/dist/scanners/rbac/patterns.js.map +1 -0
  102. package/dist/scanners/revocation/index.d.ts +8 -0
  103. package/dist/scanners/revocation/index.d.ts.map +1 -0
  104. package/dist/scanners/revocation/index.js +83 -0
  105. package/dist/scanners/revocation/index.js.map +1 -0
  106. package/dist/scanners/revocation/index.test.d.ts +5 -0
  107. package/dist/scanners/revocation/index.test.d.ts.map +1 -0
  108. package/dist/scanners/revocation/index.test.js +332 -0
  109. package/dist/scanners/revocation/index.test.js.map +1 -0
  110. package/dist/scanners/revocation/patterns.d.ts +27 -0
  111. package/dist/scanners/revocation/patterns.d.ts.map +1 -0
  112. package/dist/scanners/revocation/patterns.js +109 -0
  113. package/dist/scanners/revocation/patterns.js.map +1 -0
  114. package/dist/scanners/sanitization/index.d.ts +8 -0
  115. package/dist/scanners/sanitization/index.d.ts.map +1 -0
  116. package/dist/scanners/sanitization/index.js +98 -0
  117. package/dist/scanners/sanitization/index.js.map +1 -0
  118. package/dist/scanners/sanitization/index.test.d.ts +5 -0
  119. package/dist/scanners/sanitization/index.test.d.ts.map +1 -0
  120. package/dist/scanners/sanitization/index.test.js +370 -0
  121. package/dist/scanners/sanitization/index.test.js.map +1 -0
  122. package/dist/scanners/sanitization/patterns.d.ts +27 -0
  123. package/dist/scanners/sanitization/patterns.d.ts.map +1 -0
  124. package/dist/scanners/sanitization/patterns.js +117 -0
  125. package/dist/scanners/sanitization/patterns.js.map +1 -0
  126. package/dist/training/certificate.d.ts +26 -0
  127. package/dist/training/certificate.d.ts.map +1 -0
  128. package/dist/training/certificate.js +92 -0
  129. package/dist/training/certificate.js.map +1 -0
  130. package/dist/training/index.d.ts +3 -0
  131. package/dist/training/index.d.ts.map +1 -0
  132. package/dist/training/index.js +243 -0
  133. package/dist/training/index.js.map +1 -0
  134. package/dist/training/modules.d.ts +13 -0
  135. package/dist/training/modules.d.ts.map +1 -0
  136. package/dist/training/modules.js +608 -0
  137. package/dist/training/modules.js.map +1 -0
  138. package/dist/training/questions.d.ts +9 -0
  139. package/dist/training/questions.d.ts.map +1 -0
  140. package/dist/training/questions.js +505 -0
  141. package/dist/training/questions.js.map +1 -0
  142. package/dist/types.d.ts +45 -0
  143. package/dist/types.d.ts.map +1 -1
  144. package/dist/utils/npm-audit.d.ts +6 -0
  145. package/dist/utils/npm-audit.d.ts.map +1 -0
  146. package/dist/utils/npm-audit.js +95 -0
  147. package/dist/utils/npm-audit.js.map +1 -0
  148. package/dist/utils/scan-history.d.ts +59 -0
  149. package/dist/utils/scan-history.d.ts.map +1 -0
  150. package/dist/utils/scan-history.js +170 -0
  151. package/dist/utils/scan-history.js.map +1 -0
  152. package/package.json +4 -1
  153. package/templates/baa-verification-letter.md +105 -0
  154. package/templates/irp.md +545 -0
  155. package/templates/notice-of-privacy-practices.md +491 -0
  156. package/templates/physical-safeguards-checklist.md +247 -0
  157. package/templates/security-officer-designation.md +237 -0
@@ -0,0 +1,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":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAElC,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAE3D,MAAM,CAAC,MAAM,oBAAoB,GAAY;IAC3C,IAAI,EAAE,gCAAgC;IACtC,QAAQ,EAAE,eAAe;IAEzB,KAAK,CAAC,IAAI,CAAC,KAAe,EAAE,OAAoB;QAC9C,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,uBAAuB;QACvB,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACnC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,CAC7B,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBACjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAElC,8CAA8C;gBAC9C,MAAM,UAAU,GAAG,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAE1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBACtB,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;oBAEzB,0CAA0C;oBAC1C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;wBAAE,SAAS;oBAE1D,oBAAoB;oBACpB,KAAK,MAAM,OAAO,IAAI,0BAA0B,EAAE,CAAC;wBACjD,uCAAuC;wBACvC,IAAI,OAAO,CAAC,EAAE,KAAK,YAAY,IAAI,UAAU;4BAAE,SAAS;wBAExD,0CAA0C;wBAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;wBAEnE,IAAI,CAAC,OAAO;4BAAE,SAAS;wBAEvB,0BAA0B;wBAC1B,MAAM,aAAa,GAAG,OAAO,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;4BACjC,OAAO,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;wBAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;4BACjC,OAAO,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;wBAE1D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC;wBACpD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC;wBAChE,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;wBAE3D,wCAAwC;wBACxC,MAAM,eAAe,GAAG,YAAY;6BACjC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;6BAC5E,IAAI,CAAC,IAAI,CAAC,CAAC;wBAEd,kDAAkD;wBAClD,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;4BACtD,4DAA4D;4BAC5D,IAAI,OAAO,CAAC,EAAE,KAAK,YAAY,EAAE,CAAC;gCAChC,OAAO,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;4BACrC,CAAC;4BAED,+DAA+D;4BAC/D,IAAI,OAAO,CAAC,EAAE,KAAK,YAAY,EAAE,CAAC;gCAChC,OAAO,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;4BACrC,CAAC;4BAED,sEAAsE;4BACtE,OAAO,KAAK,CAAC;wBACf,CAAC,CAAC,CAAC;wBAEH,IAAI,MAAM;4BAAE,SAAS;wBAErB,iBAAiB;wBACjB,MAAM,OAAO,GAAY;4BACvB,EAAE,EAAE,OAAO,CAAC,EAAE;4BACd,QAAQ,EAAE,OAAO,CAAC,QAAe;4BACjC,QAAQ,EAAE,OAAO,CAAC,QAAQ;4BAC1B,KAAK,EAAE,OAAO,CAAC,IAAI;4BACnB,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,aAAa,IAAI,CAAC,IAAI,EAAE,EAAE;4BAC7D,IAAI,EAAE,IAAI;4BACV,IAAI,EAAE,UAAU;4BAChB,cAAc,EAAE,OAAO,CAAC,cAAc;4BACtC,cAAc,EAAE,OAAO,CAAC,cAAc;4BACtC,UAAU,EAAE,MAAM;yBACnB,CAAC;wBAEF,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,gCAAgC;YAClC,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Configuration Security Scanner Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/scanners/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"}