s3db.js 13.6.1 → 14.0.2

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 (189) hide show
  1. package/README.md +56 -15
  2. package/dist/s3db.cjs +72446 -39022
  3. package/dist/s3db.cjs.map +1 -1
  4. package/dist/s3db.es.js +72172 -38790
  5. package/dist/s3db.es.js.map +1 -1
  6. package/mcp/lib/base-handler.js +157 -0
  7. package/mcp/lib/handlers/connection-handler.js +280 -0
  8. package/mcp/lib/handlers/query-handler.js +533 -0
  9. package/mcp/lib/handlers/resource-handler.js +428 -0
  10. package/mcp/lib/tool-registry.js +336 -0
  11. package/mcp/lib/tools/connection-tools.js +161 -0
  12. package/mcp/lib/tools/query-tools.js +267 -0
  13. package/mcp/lib/tools/resource-tools.js +404 -0
  14. package/package.json +85 -50
  15. package/src/clients/memory-client.class.js +346 -191
  16. package/src/clients/memory-storage.class.js +300 -84
  17. package/src/clients/s3-client.class.js +7 -6
  18. package/src/concerns/geo-encoding.js +19 -2
  19. package/src/concerns/ip.js +59 -9
  20. package/src/concerns/money.js +8 -1
  21. package/src/concerns/password-hashing.js +49 -8
  22. package/src/concerns/plugin-storage.js +186 -18
  23. package/src/concerns/storage-drivers/filesystem-driver.js +284 -0
  24. package/src/database.class.js +139 -29
  25. package/src/errors.js +332 -42
  26. package/src/plugins/api/auth/oidc-auth.js +66 -17
  27. package/src/plugins/api/auth/strategies/base-strategy.class.js +74 -0
  28. package/src/plugins/api/auth/strategies/factory.class.js +63 -0
  29. package/src/plugins/api/auth/strategies/global-strategy.class.js +44 -0
  30. package/src/plugins/api/auth/strategies/path-based-strategy.class.js +83 -0
  31. package/src/plugins/api/auth/strategies/path-rules-strategy.class.js +118 -0
  32. package/src/plugins/api/concerns/failban-manager.js +106 -57
  33. package/src/plugins/api/concerns/route-context.js +601 -0
  34. package/src/plugins/api/index.js +168 -40
  35. package/src/plugins/api/routes/auth-routes.js +198 -30
  36. package/src/plugins/api/routes/resource-routes.js +19 -4
  37. package/src/plugins/api/server/health-manager.class.js +163 -0
  38. package/src/plugins/api/server/middleware-chain.class.js +310 -0
  39. package/src/plugins/api/server/router.class.js +472 -0
  40. package/src/plugins/api/server.js +280 -1303
  41. package/src/plugins/api/utils/custom-routes.js +17 -5
  42. package/src/plugins/api/utils/guards.js +76 -17
  43. package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
  44. package/src/plugins/api/utils/openapi-generator.js +7 -6
  45. package/src/plugins/audit.plugin.js +30 -8
  46. package/src/plugins/backup.plugin.js +110 -14
  47. package/src/plugins/cache/cache.class.js +22 -5
  48. package/src/plugins/cache/filesystem-cache.class.js +116 -19
  49. package/src/plugins/cache/memory-cache.class.js +211 -57
  50. package/src/plugins/cache/multi-tier-cache.class.js +371 -0
  51. package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
  52. package/src/plugins/cache/redis-cache.class.js +552 -0
  53. package/src/plugins/cache/s3-cache.class.js +17 -8
  54. package/src/plugins/cache.plugin.js +176 -61
  55. package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
  56. package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
  57. package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
  58. package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
  59. package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
  60. package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
  61. package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
  62. package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
  63. package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
  64. package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
  65. package/src/plugins/cloud-inventory/index.js +29 -8
  66. package/src/plugins/cloud-inventory/registry.js +64 -42
  67. package/src/plugins/cloud-inventory.plugin.js +240 -138
  68. package/src/plugins/concerns/plugin-dependencies.js +54 -0
  69. package/src/plugins/concerns/resource-names.js +100 -0
  70. package/src/plugins/consumers/index.js +10 -2
  71. package/src/plugins/consumers/sqs-consumer.js +12 -2
  72. package/src/plugins/cookie-farm-suite.plugin.js +278 -0
  73. package/src/plugins/cookie-farm.errors.js +73 -0
  74. package/src/plugins/cookie-farm.plugin.js +869 -0
  75. package/src/plugins/costs.plugin.js +7 -1
  76. package/src/plugins/eventual-consistency/analytics.js +94 -19
  77. package/src/plugins/eventual-consistency/config.js +15 -7
  78. package/src/plugins/eventual-consistency/consolidation.js +29 -11
  79. package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
  80. package/src/plugins/eventual-consistency/helpers.js +39 -14
  81. package/src/plugins/eventual-consistency/install.js +21 -2
  82. package/src/plugins/eventual-consistency/utils.js +32 -10
  83. package/src/plugins/fulltext.plugin.js +38 -11
  84. package/src/plugins/geo.plugin.js +61 -9
  85. package/src/plugins/identity/concerns/config.js +61 -0
  86. package/src/plugins/identity/concerns/mfa-manager.js +15 -2
  87. package/src/plugins/identity/concerns/rate-limit.js +124 -0
  88. package/src/plugins/identity/concerns/resource-schemas.js +9 -1
  89. package/src/plugins/identity/concerns/token-generator.js +29 -4
  90. package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
  91. package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
  92. package/src/plugins/identity/drivers/index.js +18 -0
  93. package/src/plugins/identity/drivers/password-driver.js +122 -0
  94. package/src/plugins/identity/email-service.js +17 -2
  95. package/src/plugins/identity/index.js +413 -69
  96. package/src/plugins/identity/oauth2-server.js +413 -30
  97. package/src/plugins/identity/oidc-discovery.js +16 -8
  98. package/src/plugins/identity/rsa-keys.js +115 -35
  99. package/src/plugins/identity/server.js +166 -45
  100. package/src/plugins/identity/session-manager.js +53 -7
  101. package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
  102. package/src/plugins/identity/ui/routes.js +363 -255
  103. package/src/plugins/importer/index.js +153 -20
  104. package/src/plugins/index.js +9 -2
  105. package/src/plugins/kubernetes-inventory/index.js +6 -0
  106. package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
  107. package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
  108. package/src/plugins/kubernetes-inventory.plugin.js +980 -0
  109. package/src/plugins/metrics.plugin.js +64 -16
  110. package/src/plugins/ml/base-model.class.js +25 -15
  111. package/src/plugins/ml/regression-model.class.js +1 -1
  112. package/src/plugins/ml.errors.js +57 -25
  113. package/src/plugins/ml.plugin.js +28 -4
  114. package/src/plugins/namespace.js +210 -0
  115. package/src/plugins/plugin.class.js +180 -8
  116. package/src/plugins/puppeteer/console-monitor.js +729 -0
  117. package/src/plugins/puppeteer/cookie-manager.js +492 -0
  118. package/src/plugins/puppeteer/network-monitor.js +816 -0
  119. package/src/plugins/puppeteer/performance-manager.js +746 -0
  120. package/src/plugins/puppeteer/proxy-manager.js +478 -0
  121. package/src/plugins/puppeteer/stealth-manager.js +556 -0
  122. package/src/plugins/puppeteer.errors.js +81 -0
  123. package/src/plugins/puppeteer.plugin.js +1327 -0
  124. package/src/plugins/queue-consumer.plugin.js +69 -14
  125. package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
  126. package/src/plugins/recon/concerns/command-runner.js +148 -0
  127. package/src/plugins/recon/concerns/diff-detector.js +372 -0
  128. package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
  129. package/src/plugins/recon/concerns/process-manager.js +338 -0
  130. package/src/plugins/recon/concerns/report-generator.js +478 -0
  131. package/src/plugins/recon/concerns/security-analyzer.js +571 -0
  132. package/src/plugins/recon/concerns/target-normalizer.js +68 -0
  133. package/src/plugins/recon/config/defaults.js +321 -0
  134. package/src/plugins/recon/config/resources.js +370 -0
  135. package/src/plugins/recon/index.js +778 -0
  136. package/src/plugins/recon/managers/dependency-manager.js +174 -0
  137. package/src/plugins/recon/managers/scheduler-manager.js +179 -0
  138. package/src/plugins/recon/managers/storage-manager.js +745 -0
  139. package/src/plugins/recon/managers/target-manager.js +274 -0
  140. package/src/plugins/recon/stages/asn-stage.js +314 -0
  141. package/src/plugins/recon/stages/certificate-stage.js +84 -0
  142. package/src/plugins/recon/stages/dns-stage.js +107 -0
  143. package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
  144. package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
  145. package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
  146. package/src/plugins/recon/stages/http-stage.js +89 -0
  147. package/src/plugins/recon/stages/latency-stage.js +148 -0
  148. package/src/plugins/recon/stages/massdns-stage.js +302 -0
  149. package/src/plugins/recon/stages/osint-stage.js +1373 -0
  150. package/src/plugins/recon/stages/ports-stage.js +169 -0
  151. package/src/plugins/recon/stages/screenshot-stage.js +94 -0
  152. package/src/plugins/recon/stages/secrets-stage.js +514 -0
  153. package/src/plugins/recon/stages/subdomains-stage.js +295 -0
  154. package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
  155. package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
  156. package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
  157. package/src/plugins/recon/stages/whois-stage.js +349 -0
  158. package/src/plugins/recon.plugin.js +75 -0
  159. package/src/plugins/recon.plugin.js.backup +2635 -0
  160. package/src/plugins/relation.errors.js +87 -14
  161. package/src/plugins/replicator.plugin.js +514 -137
  162. package/src/plugins/replicators/base-replicator.class.js +89 -1
  163. package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
  164. package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
  165. package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
  166. package/src/plugins/replicators/mysql-replicator.class.js +52 -17
  167. package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
  168. package/src/plugins/replicators/postgres-replicator.class.js +62 -27
  169. package/src/plugins/replicators/s3db-replicator.class.js +25 -18
  170. package/src/plugins/replicators/schema-sync.helper.js +3 -3
  171. package/src/plugins/replicators/sqs-replicator.class.js +8 -2
  172. package/src/plugins/replicators/turso-replicator.class.js +23 -3
  173. package/src/plugins/replicators/webhook-replicator.class.js +42 -4
  174. package/src/plugins/s3-queue.plugin.js +464 -65
  175. package/src/plugins/scheduler.plugin.js +20 -6
  176. package/src/plugins/state-machine.plugin.js +40 -9
  177. package/src/plugins/tfstate/base-driver.js +28 -4
  178. package/src/plugins/tfstate/errors.js +65 -10
  179. package/src/plugins/tfstate/filesystem-driver.js +52 -8
  180. package/src/plugins/tfstate/index.js +163 -90
  181. package/src/plugins/tfstate/s3-driver.js +64 -6
  182. package/src/plugins/ttl.plugin.js +72 -17
  183. package/src/plugins/vector/distances.js +18 -12
  184. package/src/plugins/vector/kmeans.js +26 -4
  185. package/src/resource.class.js +115 -19
  186. package/src/testing/factory.class.js +20 -3
  187. package/src/testing/seeder.class.js +7 -1
  188. package/src/clients/memory-client.md +0 -917
  189. package/src/plugins/cloud-inventory/drivers/mock-drivers.js +0 -449
@@ -0,0 +1,571 @@
1
+ /**
2
+ * SecurityAnalyzer
3
+ *
4
+ * Analyzes scan results and generates security audit checklist
5
+ * Based on OWASP Top 10, CIS benchmarks, and industry best practices
6
+ *
7
+ * Usage:
8
+ * const report = await plugin.scan('example.com', { behavior: 'aggressive' });
9
+ * const audit = SecurityAnalyzer.analyze(report);
10
+ * console.log(audit);
11
+ */
12
+
13
+ export class SecurityAnalyzer {
14
+ /**
15
+ * Analyze scan report and generate security checklist
16
+ * @param {Object} report - Scan report from ReconPlugin
17
+ * @returns {Object} Security audit with findings and recommendations
18
+ */
19
+ static analyze(report) {
20
+ const audit = {
21
+ target: report.target.host,
22
+ timestamp: report.timestamp,
23
+ summary: {
24
+ score: 0, // 0-100
25
+ grade: 'F', // A, B, C, D, F
26
+ total: 0,
27
+ passed: 0,
28
+ failed: 0,
29
+ critical: 0,
30
+ high: 0,
31
+ medium: 0,
32
+ low: 0
33
+ },
34
+ checklist: [],
35
+ recommendations: []
36
+ };
37
+
38
+ const results = report.results;
39
+
40
+ // A) Inventory Check
41
+ audit.checklist.push(this.checkInventory(results, audit.summary));
42
+
43
+ // B) Secrets Check
44
+ audit.checklist.push(this.checkSecrets(results, audit.summary));
45
+
46
+ // C) Dependencies Check (placeholder)
47
+ audit.checklist.push(this.checkDependencies(results, audit.summary));
48
+
49
+ // D) Headers & TLS Check
50
+ audit.checklist.push(this.checkSecurityHeaders(results, audit.summary));
51
+ audit.checklist.push(this.checkTLS(results, audit.summary));
52
+
53
+ // E) WAF & Rate Limiting
54
+ audit.checklist.push(this.checkWAF(results, audit.summary));
55
+
56
+ // F) Auth Check (placeholder)
57
+ audit.checklist.push(this.checkAuth(results, audit.summary));
58
+
59
+ // Calculate final score and grade
60
+ this.calculateScoreAndGrade(audit);
61
+
62
+ // Generate prioritized recommendations
63
+ this.generateRecommendations(audit);
64
+
65
+ return audit;
66
+ }
67
+
68
+ /**
69
+ * A) Inventory: subdomains, IPs, certs, CDN
70
+ */
71
+ static checkInventory(results, summary) {
72
+ const check = {
73
+ id: 'A',
74
+ name: 'Inventory',
75
+ description: 'Subdomains, IPs, certificates, CDN detection',
76
+ status: 'unknown',
77
+ findings: [],
78
+ score: 100
79
+ };
80
+
81
+ summary.total++;
82
+
83
+ // Check subdomains
84
+ if (results.subdomains) {
85
+ const count = results.subdomains.subdomains?.length || 0;
86
+
87
+ check.findings.push({
88
+ type: count > 0 ? 'pass' : 'info',
89
+ severity: 'info',
90
+ item: 'Subdomains Enumeration',
91
+ detail: `${count} subdomains discovered`,
92
+ action: count > 50 ? 'Review all subdomains for unnecessary exposure' : 'OK'
93
+ });
94
+
95
+ if (count > 100) {
96
+ check.findings.push({
97
+ type: 'warning',
98
+ severity: 'medium',
99
+ item: 'Excessive Subdomains',
100
+ detail: `${count} subdomains may indicate wildcard DNS or shadow IT`,
101
+ action: 'Review subdomain creation policies and implement DNS zone monitoring'
102
+ });
103
+ summary.medium++;
104
+ check.score -= 10;
105
+ }
106
+ }
107
+
108
+ // Check SSL certificate
109
+ if (results.certificate) {
110
+ const validTo = results.certificate.validTo;
111
+ if (validTo) {
112
+ const daysUntilExpiry = this.calculateDaysUntilExpiry(validTo);
113
+
114
+ if (daysUntilExpiry < 7) {
115
+ check.findings.push({
116
+ type: 'fail',
117
+ severity: 'critical',
118
+ item: 'Certificate Expiring',
119
+ detail: `SSL certificate expires in ${daysUntilExpiry} days`,
120
+ action: 'Renew SSL certificate IMMEDIATELY. Implement auto-renewal (Let\'s Encrypt)'
121
+ });
122
+ summary.critical++;
123
+ summary.failed++;
124
+ check.score -= 25;
125
+ } else if (daysUntilExpiry < 30) {
126
+ check.findings.push({
127
+ type: 'warning',
128
+ severity: 'high',
129
+ item: 'Certificate Expiring Soon',
130
+ detail: `SSL certificate expires in ${daysUntilExpiry} days`,
131
+ action: 'Renew SSL certificate soon. Set up expiry monitoring/alerts'
132
+ });
133
+ summary.high++;
134
+ check.score -= 15;
135
+ } else {
136
+ check.findings.push({
137
+ type: 'pass',
138
+ severity: 'info',
139
+ item: 'Certificate Validity',
140
+ detail: `SSL certificate valid for ${daysUntilExpiry} days`
141
+ });
142
+ }
143
+ }
144
+ }
145
+
146
+ // Check CDN
147
+ if (results.osint?.categories?.saas?.services?.cdn) {
148
+ const cdn = results.osint.categories.saas.services.cdn;
149
+ check.findings.push({
150
+ type: 'pass',
151
+ severity: 'info',
152
+ item: 'CDN Detected',
153
+ detail: `Using ${cdn.provider}`,
154
+ action: 'CDN provides DDoS protection and performance benefits'
155
+ });
156
+ } else {
157
+ check.findings.push({
158
+ type: 'warning',
159
+ severity: 'low',
160
+ item: 'No CDN Detected',
161
+ detail: 'No CDN detected',
162
+ action: 'Consider Cloudflare, Fastly, or AWS CloudFront for DDoS protection'
163
+ });
164
+ summary.low++;
165
+ check.score -= 5;
166
+ }
167
+
168
+ check.status = check.score >= 80 ? 'pass' : (check.score >= 60 ? 'warning' : 'fail');
169
+ if (check.status === 'pass') summary.passed++;
170
+
171
+ return check;
172
+ }
173
+
174
+ /**
175
+ * B) Secrets: run gitleaks + truffleHog on repos; rotate any leaked keys
176
+ */
177
+ static checkSecrets(results, summary) {
178
+ const check = {
179
+ id: 'B',
180
+ name: 'Secrets',
181
+ description: 'Leaked API keys, credentials, tokens',
182
+ status: 'unknown',
183
+ findings: [],
184
+ score: 100
185
+ };
186
+
187
+ summary.total++;
188
+
189
+ if (results.secrets) {
190
+ const secretsFound = results.secrets.secrets?.length || 0;
191
+
192
+ if (secretsFound > 0) {
193
+ check.findings.push({
194
+ type: 'fail',
195
+ severity: 'critical',
196
+ item: 'Secrets Exposed',
197
+ detail: `${secretsFound} potential secrets found publicly`,
198
+ action: 'IMMEDIATE: Rotate all exposed keys, tokens, credentials. Revoke compromised secrets. Review commit history.'
199
+ });
200
+ summary.critical += secretsFound;
201
+ summary.failed++;
202
+ check.score = 0; // Automatic fail
203
+ check.status = 'fail';
204
+ } else {
205
+ check.findings.push({
206
+ type: 'pass',
207
+ severity: 'info',
208
+ item: 'No Secrets Detected',
209
+ detail: 'No exposed secrets found',
210
+ action: 'Continue monitoring. Implement pre-commit hooks (gitleaks, truffleHog)'
211
+ });
212
+ summary.passed++;
213
+ check.status = 'pass';
214
+ }
215
+ } else {
216
+ check.findings.push({
217
+ type: 'info',
218
+ severity: 'info',
219
+ item: 'Secrets Scan Not Run',
220
+ detail: 'Secrets detection stage was not executed',
221
+ action: 'Run scan with secrets detection enabled'
222
+ });
223
+ check.status = 'unknown';
224
+ }
225
+
226
+ return check;
227
+ }
228
+
229
+ /**
230
+ * C) Dependencies: run Snyk/Dependabot and patch high/critical
231
+ */
232
+ static checkDependencies(results, summary) {
233
+ const check = {
234
+ id: 'C',
235
+ name: 'Dependencies',
236
+ description: 'Vulnerable packages (requires manual setup)',
237
+ status: 'manual',
238
+ findings: [{
239
+ type: 'info',
240
+ severity: 'info',
241
+ item: 'Manual Check Required',
242
+ detail: 'Dependency scanning requires package.json/requirements.txt access',
243
+ action: 'Run: npm audit, yarn audit, snyk test, or GitHub Dependabot. Patch high/critical vulnerabilities.'
244
+ }],
245
+ score: 0
246
+ };
247
+
248
+ summary.total++;
249
+
250
+ return check;
251
+ }
252
+
253
+ /**
254
+ * D) Headers & TLS: enforce HSTS, CSP, secure cookies, TLS1.2+/modern ciphers
255
+ */
256
+ static checkSecurityHeaders(results, summary) {
257
+ const check = {
258
+ id: 'D1',
259
+ name: 'Security Headers',
260
+ description: 'HSTS, CSP, X-Frame-Options, etc.',
261
+ status: 'unknown',
262
+ findings: [],
263
+ score: 100
264
+ };
265
+
266
+ summary.total++;
267
+
268
+ if (results.http?.headers) {
269
+ const headers = results.http.headers;
270
+
271
+ // HSTS
272
+ if (!headers['strict-transport-security']) {
273
+ check.findings.push({
274
+ type: 'fail',
275
+ severity: 'high',
276
+ item: 'Missing HSTS',
277
+ detail: 'Strict-Transport-Security header not found',
278
+ action: 'Add header: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload'
279
+ });
280
+ summary.high++;
281
+ check.score -= 20;
282
+ } else {
283
+ check.findings.push({
284
+ type: 'pass',
285
+ severity: 'info',
286
+ item: 'HSTS Enabled',
287
+ detail: headers['strict-transport-security']
288
+ });
289
+ }
290
+
291
+ // CSP
292
+ if (!headers['content-security-policy'] && !headers['content-security-policy-report-only']) {
293
+ check.findings.push({
294
+ type: 'fail',
295
+ severity: 'medium',
296
+ item: 'Missing CSP',
297
+ detail: 'Content-Security-Policy header not found',
298
+ action: 'Implement CSP to prevent XSS. Start with report-only mode.'
299
+ });
300
+ summary.medium++;
301
+ check.score -= 15;
302
+ } else {
303
+ check.findings.push({
304
+ type: 'pass',
305
+ severity: 'info',
306
+ item: 'CSP Present',
307
+ detail: 'Content-Security-Policy configured'
308
+ });
309
+ }
310
+
311
+ // X-Frame-Options
312
+ if (!headers['x-frame-options']) {
313
+ check.findings.push({
314
+ type: 'fail',
315
+ severity: 'medium',
316
+ item: 'Missing X-Frame-Options',
317
+ detail: 'Clickjacking protection not found',
318
+ action: 'Add header: X-Frame-Options: DENY or SAMEORIGIN'
319
+ });
320
+ summary.medium++;
321
+ check.score -= 10;
322
+ }
323
+
324
+ // X-Content-Type-Options
325
+ if (!headers['x-content-type-options']) {
326
+ check.findings.push({
327
+ type: 'warning',
328
+ severity: 'low',
329
+ item: 'Missing X-Content-Type-Options',
330
+ detail: 'MIME-sniffing protection not found',
331
+ action: 'Add header: X-Content-Type-Options: nosniff'
332
+ });
333
+ summary.low++;
334
+ check.score -= 5;
335
+ }
336
+ }
337
+
338
+ check.status = check.score >= 80 ? 'pass' : (check.score >= 60 ? 'warning' : 'fail');
339
+ if (check.status === 'pass') summary.passed++;
340
+ else if (check.status === 'fail') summary.failed++;
341
+
342
+ return check;
343
+ }
344
+
345
+ /**
346
+ * D) TLS Configuration
347
+ */
348
+ static checkTLS(results, summary) {
349
+ const check = {
350
+ id: 'D2',
351
+ name: 'TLS Configuration',
352
+ description: 'TLS 1.2+, modern ciphers',
353
+ status: 'unknown',
354
+ findings: [],
355
+ score: 100
356
+ };
357
+
358
+ summary.total++;
359
+
360
+ if (results.tlsAudit) {
361
+ const tlsOk = results.tlsAudit.tools?.openssl?.status === 'ok';
362
+
363
+ if (tlsOk) {
364
+ check.findings.push({
365
+ type: 'pass',
366
+ severity: 'info',
367
+ item: 'TLS Available',
368
+ detail: 'TLS connection successful',
369
+ action: 'Ensure TLS 1.2+ only. Disable TLS 1.0/1.1. Use modern cipher suites (sslyze/testssl for details).'
370
+ });
371
+ summary.passed++;
372
+ check.status = 'pass';
373
+ } else {
374
+ check.findings.push({
375
+ type: 'fail',
376
+ severity: 'critical',
377
+ item: 'TLS Connection Failed',
378
+ detail: 'Unable to establish TLS connection',
379
+ action: 'Verify SSL/TLS configuration and certificate validity'
380
+ });
381
+ summary.critical++;
382
+ summary.failed++;
383
+ check.score = 0;
384
+ check.status = 'fail';
385
+ }
386
+ }
387
+
388
+ return check;
389
+ }
390
+
391
+ /**
392
+ * E) WAF & rate-limiting: enable, tune false-positives
393
+ */
394
+ static checkWAF(results, summary) {
395
+ const check = {
396
+ id: 'E',
397
+ name: 'WAF & Rate Limiting',
398
+ description: 'Web Application Firewall detection',
399
+ status: 'unknown',
400
+ findings: [],
401
+ score: 100
402
+ };
403
+
404
+ summary.total++;
405
+
406
+ // Check for WAF via headers or CDN
407
+ const hasCloudflare = results.osint?.categories?.saas?.services?.cdn?.provider?.includes('Cloudflare');
408
+ const hasWAFHeader = results.http?.headers?.['cf-ray'] || results.http?.headers?.['x-sucuri-id'];
409
+
410
+ if (hasCloudflare || hasWAFHeader) {
411
+ check.findings.push({
412
+ type: 'pass',
413
+ severity: 'info',
414
+ item: 'WAF Detected',
415
+ detail: hasCloudflare ? 'Cloudflare WAF detected' : 'WAF headers detected',
416
+ action: 'WAF is active. Monitor and tune rules regularly. Review false positives.'
417
+ });
418
+ summary.passed++;
419
+ check.status = 'pass';
420
+ } else {
421
+ check.findings.push({
422
+ type: 'warning',
423
+ severity: 'medium',
424
+ item: 'No WAF Detected',
425
+ detail: 'No Web Application Firewall detected',
426
+ action: 'Implement WAF (Cloudflare, AWS WAF, Akamai) for OWASP Top 10 protection. Configure rate limiting.'
427
+ });
428
+ summary.medium++;
429
+ check.score -= 15;
430
+ check.status = 'warning';
431
+ }
432
+
433
+ return check;
434
+ }
435
+
436
+ /**
437
+ * F) Auth: check password policies, MFA, session timeouts, brute-force protection
438
+ */
439
+ static checkAuth(results, summary) {
440
+ const check = {
441
+ id: 'F',
442
+ name: 'Authentication',
443
+ description: 'Password policies, MFA, sessions (manual)',
444
+ status: 'manual',
445
+ findings: [{
446
+ type: 'info',
447
+ severity: 'info',
448
+ item: 'Manual Check Required',
449
+ detail: 'Authentication audit requires authenticated scan',
450
+ action: 'Verify: password policies (min 12 chars, complexity), MFA enforcement, session timeouts (15-30 min), brute-force protection (rate limiting, CAPTCHA)'
451
+ }],
452
+ score: 0
453
+ };
454
+
455
+ summary.total++;
456
+
457
+ return check;
458
+ }
459
+
460
+ /**
461
+ * Calculate overall score and grade
462
+ */
463
+ static calculateScoreAndGrade(audit) {
464
+ let totalScore = 0;
465
+ let scoredChecks = 0;
466
+
467
+ for (const check of audit.checklist) {
468
+ if (check.status !== 'manual' && check.status !== 'unknown') {
469
+ totalScore += check.score;
470
+ scoredChecks++;
471
+ }
472
+ }
473
+
474
+ audit.summary.score = scoredChecks > 0 ? Math.round(totalScore / scoredChecks) : 0;
475
+
476
+ // Assign grade
477
+ if (audit.summary.score >= 90) audit.summary.grade = 'A';
478
+ else if (audit.summary.score >= 80) audit.summary.grade = 'B';
479
+ else if (audit.summary.score >= 70) audit.summary.grade = 'C';
480
+ else if (audit.summary.score >= 60) audit.summary.grade = 'D';
481
+ else audit.summary.grade = 'F';
482
+ }
483
+
484
+ /**
485
+ * Generate prioritized recommendations
486
+ */
487
+ static generateRecommendations(audit) {
488
+ const recommendations = [];
489
+
490
+ for (const check of audit.checklist) {
491
+ for (const finding of check.findings) {
492
+ if (finding.type === 'fail' && finding.action) {
493
+ recommendations.push({
494
+ priority: finding.severity === 'critical' ? 1 : (finding.severity === 'high' ? 2 : 3),
495
+ severity: finding.severity,
496
+ category: check.name,
497
+ item: finding.item,
498
+ action: finding.action
499
+ });
500
+ }
501
+ }
502
+ }
503
+
504
+ // Sort by priority
505
+ recommendations.sort((a, b) => a.priority - b.priority);
506
+
507
+ audit.recommendations = recommendations;
508
+ }
509
+
510
+ /**
511
+ * Helper: Calculate days until SSL expiry
512
+ */
513
+ static calculateDaysUntilExpiry(validToDate) {
514
+ if (!validToDate) return null;
515
+
516
+ const expiry = new Date(validToDate);
517
+ const now = new Date();
518
+ const diffTime = expiry - now;
519
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
520
+
521
+ return diffDays;
522
+ }
523
+
524
+ /**
525
+ * Generate markdown report
526
+ */
527
+ static generateMarkdownReport(audit) {
528
+ let md = `# Security Audit Report\n\n`;
529
+ md += `**Target:** ${audit.target}\n`;
530
+ md += `**Date:** ${new Date(audit.timestamp).toLocaleString()}\n`;
531
+ md += `**Score:** ${audit.summary.score}/100 (Grade: ${audit.summary.grade})\n\n`;
532
+
533
+ md += `## Summary\n\n`;
534
+ md += `- Total Checks: ${audit.summary.total}\n`;
535
+ md += `- Passed: ${audit.summary.passed}\n`;
536
+ md += `- Failed: ${audit.summary.failed}\n`;
537
+ md += `- Critical: ${audit.summary.critical}\n`;
538
+ md += `- High: ${audit.summary.high}\n`;
539
+ md += `- Medium: ${audit.summary.medium}\n`;
540
+ md += `- Low: ${audit.summary.low}\n\n`;
541
+
542
+ md += `## Checklist\n\n`;
543
+
544
+ for (const check of audit.checklist) {
545
+ const statusIcon = check.status === 'pass' ? '✅' : (check.status === 'fail' ? '❌' : '⚠️');
546
+ md += `### ${statusIcon} ${check.id}) ${check.name}\n`;
547
+ md += `*${check.description}*\n\n`;
548
+
549
+ for (const finding of check.findings) {
550
+ const icon = finding.type === 'pass' ? '✓' : (finding.type === 'fail' ? '✗' : 'ℹ');
551
+ md += `- ${icon} **${finding.item}**: ${finding.detail}\n`;
552
+ if (finding.action) {
553
+ md += ` - Action: ${finding.action}\n`;
554
+ }
555
+ }
556
+
557
+ md += `\n`;
558
+ }
559
+
560
+ if (audit.recommendations.length > 0) {
561
+ md += `## Priority Recommendations\n\n`;
562
+
563
+ for (const rec of audit.recommendations) {
564
+ md += `${rec.priority}. **[${rec.severity.toUpperCase()}]** ${rec.item}\n`;
565
+ md += ` - ${rec.action}\n\n`;
566
+ }
567
+ }
568
+
569
+ return md;
570
+ }
571
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * TargetNormalizer
3
+ *
4
+ * Normalizes target URLs/domains into structured format:
5
+ * - Parses URLs
6
+ * - Extracts host, protocol, port
7
+ * - Handles edge cases
8
+ */
9
+
10
+ export class TargetNormalizer {
11
+ /**
12
+ * Normalize target input to structured format
13
+ */
14
+ static normalize(target) {
15
+ if (!target || typeof target !== 'string') {
16
+ throw new Error('Target must be a non-empty string');
17
+ }
18
+
19
+ let url;
20
+ try {
21
+ url = new URL(target.includes('://') ? target : `https://${target}`);
22
+ } catch (error) {
23
+ url = new URL(`https://${target}`);
24
+ }
25
+
26
+ const protocol = url.protocol ? url.protocol.replace(':', '') : null;
27
+ const host = url.hostname || target;
28
+ const port = url.port ? Number(url.port) : this.defaultPortForProtocol(protocol);
29
+
30
+ return {
31
+ original: target,
32
+ host,
33
+ protocol,
34
+ port,
35
+ path: url.pathname === '/' ? null : url.pathname
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Get default port for protocol
41
+ */
42
+ static defaultPortForProtocol(protocol) {
43
+ switch (protocol) {
44
+ case 'http':
45
+ return 80;
46
+ case 'https':
47
+ return 443;
48
+ case 'ftp':
49
+ return 21;
50
+ case 'ssh':
51
+ return 22;
52
+ default:
53
+ return null;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Build full URL from normalized target
59
+ */
60
+ static buildUrl(target) {
61
+ const protocol = target.protocol || 'https';
62
+ const port = target.port && target.port !== this.defaultPortForProtocol(protocol)
63
+ ? `:${target.port}`
64
+ : '';
65
+ const path = target.path || '';
66
+ return `${protocol}://${target.host}${port}${path}`;
67
+ }
68
+ }