cipher-shield 1.0.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/src/shield.js ADDED
@@ -0,0 +1,694 @@
1
+ /**
2
+ * cipher-shield v2.1 - Production Security Middleware
3
+ *
4
+ * A comprehensive, multi-layered security middleware for Node.js/Express applications
5
+ * providing AES encryption, ghost route protection, shadow banning, and AI-powered
6
+ * threat detection with adaptive DEFCON escalation.
7
+ *
8
+ * @author Omindu Dissanayaka
9
+ * @version 1.0.0
10
+ * @license MIT
11
+ */
12
+
13
+ const ghostHandler = require('./modules/ghostHandler');
14
+ const shadowHandler = require('./modules/shadowHandler');
15
+ const aiScanner = require('./modules/aiScanner');
16
+ const aesEngine = require('./core/aesEngine');
17
+ const defconSystem = require('./core/defconSystem');
18
+ const blacklistMem = require('./core/blacklistMem');
19
+ const SSLManager = require('./sslManager');
20
+ const helmet = require('helmet');
21
+ const rateLimit = require('express-rate-limit');
22
+ const onHeaders = require('on-headers');
23
+ const fs = require('fs');
24
+ const path = require('path');
25
+
26
+ const packageJsonPath = path.join(__dirname, '..', 'package.json');
27
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
28
+ const CIPHER_SHIELD_VERSION = packageJson.version;
29
+
30
+ /**
31
+ * Generates a random security signature for header obfuscation
32
+ *
33
+ * @private
34
+ * @returns {string} Random security signature
35
+ */
36
+ function generateRandomSignature() {
37
+ const signatures = [
38
+ 'Cipher Shield',
39
+ 'Security Shield',
40
+ 'Defense Matrix',
41
+ 'Protection Core',
42
+ 'Security Engine',
43
+ 'Defense System',
44
+ 'Shield Protocol',
45
+ 'Security Framework',
46
+ 'Defense Network',
47
+ 'Protection Layer',
48
+ 'Security Vault',
49
+ 'Defense Core',
50
+ 'Shield Matrix',
51
+ 'Security Grid',
52
+ 'Defense Protocol'
53
+ ];
54
+
55
+ return signatures[Math.floor(Math.random() * signatures.length)];
56
+ }
57
+
58
+ /**
59
+ * Default strict helmet configuration for maximum security
60
+ * Military-grade HTTP security headers
61
+ */
62
+ const defaultStrictConfig = {
63
+ contentSecurityPolicy: {
64
+ directives: {
65
+ defaultSrc: ["'self'"],
66
+ scriptSrc: ["'self'"],
67
+ styleSrc: ["'self'", "'unsafe-inline'"],
68
+ imgSrc: ["'self'", "data:", "https:"],
69
+ fontSrc: ["'self'", "https:", "data:"],
70
+ connectSrc: ["'self'"],
71
+ mediaSrc: ["'self'"],
72
+ objectSrc: ["'none'"],
73
+ frameSrc: ["'none'"],
74
+ baseUri: ["'self'"],
75
+ formAction: ["'self'"],
76
+ upgradeInsecureRequests: []
77
+ }
78
+ },
79
+ hsts: {
80
+ maxAge: 31536000,
81
+ includeSubDomains: true,
82
+ preload: true
83
+ },
84
+ noSniff: true,
85
+ xssFilter: true,
86
+ frameguard: {
87
+ action: 'deny'
88
+ },
89
+ referrerPolicy: {
90
+ policy: 'strict-origin-when-cross-origin'
91
+ },
92
+ permissionsPolicy: {
93
+ features: {
94
+ camera: ["'none'"],
95
+ microphone: ["'none'"],
96
+ geolocation: ["'none'"],
97
+ payment: ["'self'"]
98
+ }
99
+ }
100
+ };
101
+
102
+ /**
103
+ * Creates helmet middleware based on configuration
104
+ * @param {Object} config - Headers configuration
105
+ * @returns {Function} Helmet middleware function
106
+ */
107
+ function createHelmetMiddleware(config) {
108
+ if (!config.enabled) {
109
+ return (req, res, next) => next();
110
+ }
111
+
112
+ let helmetConfig = {};
113
+
114
+ if (config.simple) {
115
+ helmetConfig = {};
116
+ } else if (config.security === 'max' || config.strict) {
117
+ helmetConfig = { ...defaultStrictConfig };
118
+ } else {
119
+ helmetConfig = {
120
+ contentSecurityPolicy: {
121
+ directives: {
122
+ defaultSrc: ["'self'"],
123
+ scriptSrc: ["'self'", "'unsafe-inline'"],
124
+ styleSrc: ["'self'", "'unsafe-inline'"],
125
+ imgSrc: ["'self'", "data:", "https:"],
126
+ connectSrc: ["'self'"],
127
+ objectSrc: ["'none'"]
128
+ }
129
+ },
130
+ hsts: {
131
+ maxAge: 86400,
132
+ includeSubDomains: false
133
+ },
134
+ noSniff: true,
135
+ xssFilter: true,
136
+ frameguard: {
137
+ action: 'sameorigin'
138
+ }
139
+ };
140
+ }
141
+
142
+ if (config.options && typeof config.options === 'object') {
143
+ helmetConfig = { ...helmetConfig, ...config.options };
144
+ }
145
+
146
+ return helmet(helmetConfig);
147
+ }
148
+
149
+ /**
150
+ * Creates rate limiter middleware based on configuration
151
+ * @param {Object} config - Rate limit configuration
152
+ * @param {Object} smartLogger - SmartLogger instance for logging (optional)
153
+ * @returns {Function} Rate limiter middleware function
154
+ */
155
+ function createRateLimitMiddleware(config, smartLogger = null) {
156
+ if (!config.enabled) {
157
+ return (req, res, next) => next();
158
+ }
159
+
160
+ let rateLimitConfig = {
161
+ windowMs: config.windowMs,
162
+ max: config.max,
163
+ message: config.message,
164
+ standardHeaders: config.standardHeaders,
165
+ legacyHeaders: config.legacyHeaders,
166
+ skipSuccessfulRequests: config.skipSuccessfulRequests,
167
+ skipFailedRequests: config.skipFailedRequests
168
+ };
169
+
170
+ if (config.options && typeof config.options === 'object') {
171
+ rateLimitConfig = { ...rateLimitConfig, ...config.options };
172
+ }
173
+
174
+ return rateLimit(rateLimitConfig);
175
+ }
176
+
177
+ /**
178
+ * Utility function to extract client IP address from request
179
+ * Handles various proxy headers and fallbacks
180
+ */
181
+ function extractClientIP(req) {
182
+ const forwarded = req.headers['x-forwarded-for'];
183
+ if (forwarded) {
184
+ return forwarded.split(',')[0].trim();
185
+ }
186
+
187
+ const realIP = req.headers['x-real-ip'];
188
+ if (realIP) {
189
+ return realIP;
190
+ }
191
+
192
+ const clientIP = req.headers['x-client-ip'];
193
+ if (clientIP) {
194
+ return clientIP;
195
+ }
196
+
197
+ const remoteAddress = req.connection?.remoteAddress ||
198
+ req.socket?.remoteAddress ||
199
+ req.connection?.socket?.remoteAddress;
200
+
201
+ if (remoteAddress) {
202
+ return remoteAddress.replace(/^::ffff:/, '');
203
+ }
204
+
205
+ return req.ip || 'unknown';
206
+ }
207
+
208
+ /**
209
+ * Validates IP address format to prevent injection attacks
210
+ *
211
+ * @private
212
+ * @param {string} ip - IP address to validate
213
+ * @returns {boolean} True if IP is valid format
214
+ */
215
+ function isValidIP(ip) {
216
+ if (!ip || typeof ip !== 'string') return false;
217
+
218
+ const ipv4Regex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
219
+ if (ipv4Regex.test(ip)) {
220
+ return ip.split('.').every(part => {
221
+ const num = parseInt(part, 10);
222
+ return num >= 0 && num <= 255;
223
+ });
224
+ }
225
+
226
+ const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
227
+ return ipv6Regex.test(ip);
228
+ }
229
+
230
+ /**
231
+ * Adds security branding to blocked response objects
232
+ *
233
+ * @private
234
+ * @param {Object} responseObj - The response object to brand
235
+ * @param {Object} signatureConfig - Signature configuration
236
+ * @returns {Object} Branded response object
237
+ */
238
+ function addSecurityBranding(responseObj, signatureConfig) {
239
+ if (!signatureConfig.enabled || !signatureConfig.branding) {
240
+ return responseObj;
241
+ }
242
+
243
+ return {
244
+ ...responseObj,
245
+ security_provider: signatureConfig.simple ?
246
+ signatureConfig.protectedBy :
247
+ signatureConfig.server
248
+ };
249
+ }
250
+
251
+ /**
252
+ * Validates and normalizes cipher-shield configuration
253
+ * Ensures all required settings are present and valid
254
+ *
255
+ * @private
256
+ * @param {Object} config - Raw configuration object
257
+ * @returns {Object} Normalized and validated configuration
258
+ * @throws {Error} If configuration is invalid
259
+ */
260
+ function validateAndNormalizeConfig(config = {}) {
261
+ const settings = {
262
+ encryption: {
263
+ enabled: Boolean(config.encryption?.enabled),
264
+ secretKey: config.encryption?.secretKey || null,
265
+ algorithm: config.encryption?.algorithm || 'aes-256-gcm'
266
+ },
267
+ ghostRoutes: Array.isArray(config.ghostRoutes) ? config.ghostRoutes : [],
268
+ shadowBan: {
269
+ enabled: Boolean(config.shadowBan?.enabled),
270
+ delayTime: Math.max(1000, config.shadowBan?.delayTime || 20000)
271
+ },
272
+ aiGate: {
273
+ enabled: Boolean(config.aiGate?.enabled),
274
+ provider: config.aiGate?.provider || 'gemini',
275
+ gemini: {
276
+ apiKey: config.aiGate?.gemini?.apiKey || null,
277
+ model: config.aiGate?.gemini?.model || 'gemini-2.5-flash'
278
+ },
279
+ openai: {
280
+ apiKey: config.aiGate?.openai?.apiKey || null,
281
+ model: config.aiGate?.openai?.model || 'gpt-4o-mini',
282
+ organization: config.aiGate?.openai?.organization || null
283
+ },
284
+ scanRoutes: Array.isArray(config.aiGate?.scanRoutes) ? config.aiGate.scanRoutes : [],
285
+ failSafe: config.aiGate?.failSafe !== false
286
+ },
287
+ headers: {
288
+ enabled: config.headers?.enabled !== false,
289
+ simple: Boolean(config.headers?.simple),
290
+ security: config.headers?.security || 'standard',
291
+ strict: Boolean(config.headers?.strict),
292
+ options: config.headers?.options || {}
293
+ },
294
+ rateLimit: {
295
+ enabled: config.rateLimit?.enabled !== false,
296
+ simple: Boolean(config.rateLimit?.simple),
297
+ windowMs: config.rateLimit?.windowMs || 15 * 60 * 1000,
298
+ max: config.rateLimit?.max || 100,
299
+ message: config.rateLimit?.message || 'Too many requests from this IP, please try again later.',
300
+ standardHeaders: config.rateLimit?.standardHeaders !== false,
301
+ legacyHeaders: Boolean(config.rateLimit?.legacyHeaders),
302
+ skipSuccessfulRequests: Boolean(config.rateLimit?.skipSuccessfulRequests),
303
+ skipFailedRequests: Boolean(config.rateLimit?.skipFailedRequests),
304
+ options: config.rateLimit?.options || {}
305
+ },
306
+ signature: {
307
+ enabled: config.signature?.enabled !== false,
308
+ simple: Boolean(config.signature?.simple),
309
+ headerValue: config.signature?.headerValue || 'Cipher Shield',
310
+ randomize: Boolean(config.signature?.randomize),
311
+ customHeaderName: config.signature?.customHeaderName || 'X-Protected-By',
312
+ server: config.signature?.customServer ?
313
+ `${config.signature.customServer}/${CIPHER_SHIELD_VERSION}` :
314
+ `CipherShield/${CIPHER_SHIELD_VERSION}`,
315
+ removePoweredBy: config.signature?.removePoweredBy !== false,
316
+ branding: config.signature?.branding !== false
317
+ },
318
+ adaptiveDefcon: config.adaptiveDefcon !== false
319
+ };
320
+
321
+ if (settings.encryption.enabled) {
322
+ try {
323
+ const algoInfo = aesEngine.getAlgorithmInfo(settings.encryption.algorithm);
324
+
325
+ if (!settings.encryption.secretKey || settings.encryption.secretKey.length !== algoInfo.keyLength) {
326
+ throw new Error(
327
+ `${settings.encryption.algorithm} requires a ${algoInfo.keyLength}-character hex-encoded secret key`
328
+ );
329
+ }
330
+
331
+ if (!/^[0-9a-fA-F]+$/.test(settings.encryption.secretKey)) {
332
+ throw new Error(`Secret key must be valid hexadecimal for ${settings.encryption.algorithm}`);
333
+ }
334
+ } catch (error) {
335
+ throw new Error(`cipher-shield: ${error.message}`);
336
+ }
337
+ }
338
+
339
+ if (settings.aiGate.enabled) {
340
+ if (settings.aiGate.provider === 'gemini' && !settings.aiGate.gemini.apiKey) {
341
+ throw new Error('Gemini API key is required when using Gemini provider');
342
+ }
343
+ if (settings.aiGate.provider === 'openai' && !settings.aiGate.openai.apiKey) {
344
+ throw new Error('OpenAI API key is required when using OpenAI provider');
345
+ }
346
+ if (!['gemini', 'openai'].includes(settings.aiGate.provider)) {
347
+ throw new Error('AI provider must be either "gemini" or "openai"');
348
+ }
349
+ }
350
+
351
+ if (settings.shadowBan.enabled && settings.shadowBan.delayTime > 45000) {
352
+ throw new Error('Shadow ban delay time cannot exceed 45 seconds (45000ms)');
353
+ }
354
+
355
+ return settings;
356
+ }
357
+
358
+ /**
359
+ * CipherShield - Production Security Middleware Class
360
+ *
361
+ * A comprehensive, multi-layered security middleware for Node.js/Express applications
362
+ * providing AES encryption, ghost route protection, shadow banning, AI-powered
363
+ * threat detection, adaptive DEFCON escalation, and automated SSL certificate management.
364
+ *
365
+ * @class CipherShield
366
+ * @version 1.0.0
367
+ * @author Omindu Dissanayaka
368
+ * @license MIT
369
+ */
370
+ class CipherShield {
371
+ /**
372
+ * Creates a CipherShield instance
373
+ *
374
+ * @param {Object} config - Configuration object
375
+ */
376
+ constructor(config = {}) {
377
+ this.config = validateAndNormalizeConfig(config);
378
+ this.sslManager = null;
379
+
380
+ this.helmetMiddleware = createHelmetMiddleware(this.config.headers);
381
+
382
+ this.rateLimitMiddleware = createRateLimitMiddleware(this.config.rateLimit);
383
+
384
+ this.algoInfo = this.config.encryption.enabled ?
385
+ aesEngine.getAlgorithmInfo(this.config.encryption.algorithm) : null;
386
+
387
+ if (this.config.adaptiveDefcon) {
388
+ defconSystem.initialize();
389
+ }
390
+ }
391
+
392
+ /**
393
+ * Get the Express middleware function
394
+ *
395
+ * @returns {Function} Express middleware function
396
+ */
397
+ middleware() {
398
+ return this.createMiddleware();
399
+ }
400
+
401
+ /**
402
+ * Enable automated SSL certificate management
403
+ *
404
+ * @param {Object} sslConfig - SSL configuration
405
+ * @param {string} sslConfig.email - Email for Let's Encrypt account
406
+ * @param {string|string[]} sslConfig.domains - Domain(s) to obtain certificates for
407
+ * @param {boolean} [sslConfig.staging=true] - Use staging environment
408
+ * @param {string} [sslConfig.certDir] - Certificate storage directory
409
+ * @param {Object} [sslConfig.expressApp] - Express app for HTTP-01 challenges
410
+ * @returns {SSLManager} SSL Manager instance
411
+ */
412
+ async enableSSL(sslConfig) {
413
+ if (!sslConfig.email) {
414
+ throw new Error('SSL configuration requires an email address');
415
+ }
416
+ if (!sslConfig.domains || (Array.isArray(sslConfig.domains) && sslConfig.domains.length === 0)) {
417
+ throw new Error('SSL configuration requires at least one domain');
418
+ }
419
+
420
+ const fullSSLConfig = {
421
+ ...sslConfig,
422
+ expressApp: sslConfig.expressApp || this.config.expressApp
423
+ };
424
+
425
+ this.sslManager = new SSLManager(fullSSLConfig);
426
+ await this.sslManager.initialize();
427
+
428
+ return this.sslManager;
429
+ }
430
+
431
+ /**
432
+ * Get SSL certificates
433
+ *
434
+ * @param {string} [domain] - Specific domain, or all if not provided
435
+ * @returns {Object|Object[]|null} Certificate data
436
+ */
437
+ getSSLCertificates(domain) {
438
+ if (!this.sslManager) {
439
+ return null;
440
+ }
441
+
442
+ if (domain) {
443
+ return this.sslManager.getCertificate(domain);
444
+ }
445
+
446
+ return this.sslManager.getAllCertificates();
447
+ }
448
+
449
+ /**
450
+ * Shutdown all services
451
+ */
452
+ async shutdown() {
453
+ if (this.sslManager) {
454
+ await this.sslManager.shutdown();
455
+ }
456
+ }
457
+
458
+ /**
459
+ * Create the middleware function
460
+ *
461
+ * @private
462
+ * @returns {Function} Express middleware function
463
+ */
464
+ createMiddleware() {
465
+ return async (req, res, next) => {
466
+ const startTime = process.hrtime.bigint();
467
+
468
+ if (this.config.signature.enabled) {
469
+ onHeaders(res, () => {
470
+ if (this.config.signature.removePoweredBy) {
471
+ res.removeHeader('X-Powered-By');
472
+ }
473
+
474
+ let headerValue = this.config.signature.headerValue;
475
+ if (this.config.signature.randomize) {
476
+ headerValue = generateRandomSignature();
477
+ }
478
+
479
+ if (this.config.signature.simple) {
480
+ res.setHeader(this.config.signature.customHeaderName, headerValue);
481
+ } else {
482
+ res.setHeader('Server', this.config.signature.server);
483
+ res.setHeader(this.config.signature.customHeaderName, headerValue);
484
+ }
485
+ });
486
+ }
487
+ };
488
+ }
489
+
490
+ /**
491
+ * Execute active defense logic (Layers 1-4)
492
+ * @private
493
+ */
494
+ async executeActiveDefense(req, res, next, startTime) {
495
+ const clientIP = extractClientIP(req);
496
+
497
+ try {
498
+ if (this.config.ghostRoutes.length > 0) {
499
+ const isGhostRoute = ghostHandler.detect(req.path, this.config.ghostRoutes);
500
+
501
+ if (isGhostRoute) {
502
+ blacklistMem.add(clientIP, 'ghost_route_access');
503
+
504
+ if (this.config.adaptiveDefcon) {
505
+ defconSystem.escalate('GHOST_ROUTE_HIT');
506
+ }
507
+
508
+ }
509
+ }
510
+
511
+ if (this.config.shadowBan.enabled && blacklistMem.isBlacklisted(clientIP)) {
512
+ const currentDefcon = this.config.adaptiveDefcon ? defconSystem.getState() : 'GREEN';
513
+ const shouldBlock = await shadowHandler.delay(
514
+ clientIP,
515
+ this.config.shadowBan.delayTime,
516
+ currentDefcon
517
+ );
518
+
519
+ if (shouldBlock) {
520
+ const processingTime = Number(process.hrtime.bigint() - startTime) / 1000000;
521
+ console.log(`[cipher-shield] Blocked ${clientIP} after ${processingTime.toFixed(2)}ms`);
522
+
523
+ return res.status(408).json(addSecurityBranding({
524
+ error: 'Request Timeout',
525
+ message: 'The server timed out waiting for the request'
526
+ }, this.config.signature));
527
+ }
528
+ }
529
+
530
+ if (this.config.encryption.enabled && (req.method === 'POST' || req.method === 'PUT')) {
531
+ if (!req.body || typeof req.body !== 'object') {
532
+ blacklistMem.add(clientIP, 'invalid_request_body');
533
+ if (this.config.adaptiveDefcon) {
534
+ defconSystem.escalate('INVALID_REQUEST_BODY');
535
+ }
536
+ return res.status(400).json(addSecurityBranding({
537
+ error: 'Bad Request',
538
+ message: 'Invalid request body'
539
+ }, this.config.signature));
540
+ }
541
+
542
+ if (req.body.payload) {
543
+ if (typeof req.body.payload !== 'string' || req.body.payload.length > 10000) {
544
+ blacklistMem.add(clientIP, 'invalid_payload_format');
545
+ if (this.config.adaptiveDefcon) {
546
+ defconSystem.escalate('INVALID_PAYLOAD_FORMAT');
547
+ }
548
+ return res.status(400).json(addSecurityBranding({
549
+ error: 'Bad Request',
550
+ message: 'Invalid payload format'
551
+ }, this.config.signature));
552
+ }
553
+
554
+ try {
555
+ const decryptedData = aesEngine.decrypt(
556
+ req.body.payload,
557
+ this.config.encryption.secretKey
558
+ );
559
+
560
+ let parsedData;
561
+ try {
562
+ const tempObj = {};
563
+ parsedData = JSON.parse(decryptedData);
564
+
565
+ if (parsedData === null || typeof parsedData !== 'object') {
566
+ throw new Error('Invalid decrypted data structure');
567
+ }
568
+
569
+ if ('__proto__' in parsedData || 'constructor' in parsedData || 'prototype' in parsedData) {
570
+ throw new Error('Potential prototype pollution detected');
571
+ }
572
+
573
+ function checkPrototypePollution(obj, depth = 0) {
574
+ if (depth > 10) throw new Error('Maximum object depth exceeded');
575
+ if (obj === null || typeof obj !== 'object') return;
576
+
577
+ if ('__proto__' in obj || 'constructor' in obj || 'prototype' in obj) {
578
+ throw new Error('Prototype pollution detected in nested object');
579
+ }
580
+
581
+ for (const key in obj) {
582
+ if (obj.hasOwnProperty(key)) {
583
+ checkPrototypePollution(obj[key], depth + 1);
584
+ }
585
+ }
586
+ }
587
+
588
+ checkPrototypePollution(parsedData);
589
+
590
+ } catch (parseError) {
591
+ throw new Error(`JSON parsing failed: ${parseError.message}`);
592
+ }
593
+
594
+ req.body = parsedData;
595
+
596
+ } catch (decryptError) {
597
+ blacklistMem.add(clientIP, `aes_decryption_failure:${this.config.encryption.algorithm}`);
598
+
599
+ if (this.config.adaptiveDefcon) {
600
+ defconSystem.escalate('AES_DECRYPTION_FAIL');
601
+ }
602
+
603
+ const processingTime = Number(process.hrtime.bigint() - startTime) / 1000000;
604
+ console.log(`[cipher-shield] Decryption failed for ${clientIP} after ${processingTime.toFixed(2)}ms`);
605
+
606
+ return res.status(400).json(addSecurityBranding({
607
+ error: 'Bad Request',
608
+ message: 'Invalid payload format'
609
+ }, this.config.signature));
610
+ }
611
+ }
612
+ }
613
+
614
+ if (this.config.aiGate.enabled) {
615
+ const shouldScanRoute = this.config.aiGate.scanRoutes.some(route =>
616
+ req.path === route || req.path.startsWith(route)
617
+ );
618
+
619
+ if (shouldScanRoute) {
620
+ const currentDefcon = this.config.adaptiveDefcon ? defconSystem.getState() : 'GREEN';
621
+
622
+ if (currentDefcon !== 'RED' || !this.config.adaptiveDefcon) {
623
+ try {
624
+ const aiConfig = {
625
+ provider: this.config.aiGate.provider,
626
+ gemini: this.config.aiGate.gemini,
627
+ openai: this.config.aiGate.openai
628
+ };
629
+
630
+ const aiResult = await aiScanner.scan(req.body, aiConfig);
631
+
632
+ if (!aiResult.safe) {
633
+ const threatLevel = aiResult.threatLevel || 0;
634
+
635
+ if (threatLevel >= 7) {
636
+ blacklistMem.add(clientIP, 'ai_high_threat');
637
+
638
+ if (this.config.adaptiveDefcon) {
639
+ defconSystem.escalate('AI_HIGH_THREAT');
640
+ }
641
+
642
+ const processingTime = Number(process.hrtime.bigint() - startTime) / 1000000;
643
+ console.log(`[cipher-shield] Blocked high threat from ${clientIP} after ${processingTime.toFixed(2)}ms`);
644
+
645
+ return res.status(403).json(addSecurityBranding({
646
+ error: 'Forbidden',
647
+ message: 'Request blocked by security policy'
648
+ }, this.config.signature));
649
+
650
+ } else if (threatLevel >= 4) {
651
+ blacklistMem.add(clientIP, 'ai_medium_threat');
652
+ }
653
+ }
654
+
655
+ } catch (aiError) {
656
+ if (this.config.aiGate.failSafe) {
657
+ if (this.config.adaptiveDefcon) {
658
+ defconSystem.escalate('AI_FAILURE');
659
+ }
660
+ } else {
661
+ const processingTime = Number(process.hrtime.bigint() - startTime) / 1000000;
662
+ console.log(`[cipher-shield] AI failure for ${clientIP} after ${processingTime.toFixed(2)}ms`);
663
+
664
+ return res.status(503).json(addSecurityBranding({
665
+ error: 'Service Unavailable',
666
+ message: 'Security validation unavailable'
667
+ }, this.config.signature));
668
+ }
669
+ }
670
+ }
671
+ }
672
+ }
673
+
674
+ const totalTime = Number(process.hrtime.bigint() - startTime) / 1000000;
675
+
676
+ if (process.env.NODE_ENV === 'development') {
677
+ console.log(`[cipher-shield] ✅ ${clientIP} passed all checks in ${totalTime.toFixed(2)}ms`);
678
+ }
679
+
680
+ next();
681
+
682
+ } catch (error) {
683
+ const processingTime = Number(process.hrtime.bigint() - startTime) / 1000000;
684
+
685
+ const sanitizedError = error.message ? error.message.substring(0, 100) : 'Unknown error';
686
+
687
+ console.error(`[cipher-shield] Middleware error for ${clientIP} after ${processingTime.toFixed(2)}ms: ${sanitizedError}`);
688
+
689
+ next();
690
+ }
691
+ }
692
+ }
693
+
694
+ module.exports = CipherShield;