xypriss 1.3.8 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +232 -254
- package/dist/cjs/mods/security/src/algorithms/hash-algorithms.js +10 -0
- package/dist/cjs/mods/security/src/algorithms/hash-algorithms.js.map +1 -1
- package/dist/cjs/mods/security/src/components/cache/cacheSys.utils.js +10 -0
- package/dist/cjs/mods/security/src/components/cache/cacheSys.utils.js.map +1 -1
- package/dist/cjs/mods/security/src/components/cache/index.js +10 -74
- package/dist/cjs/mods/security/src/components/cache/index.js.map +1 -1
- package/dist/cjs/mods/security/src/components/fortified-function/index.js +9 -0
- package/dist/cjs/mods/security/src/components/fortified-function/index.js.map +1 -1
- package/dist/cjs/mods/security/src/components/fortified-function/security/security-handler.js +10 -0
- package/dist/cjs/mods/security/src/components/fortified-function/security/security-handler.js.map +1 -1
- package/dist/cjs/mods/security/src/core/crypto.js +14 -0
- package/dist/cjs/mods/security/src/core/crypto.js.map +1 -1
- package/dist/cjs/mods/security/src/index.js +10 -4
- package/dist/cjs/mods/security/src/index.js.map +1 -1
- package/dist/cjs/shared/logger/Logger.js +374 -29
- package/dist/cjs/shared/logger/Logger.js.map +1 -1
- package/dist/cjs/src/cluster/bun-cluster-manager.js +91 -1
- package/dist/cjs/src/cluster/bun-cluster-manager.js.map +1 -1
- package/dist/cjs/src/cluster/cluster-manager.js +15 -3
- package/dist/cjs/src/cluster/cluster-manager.js.map +1 -1
- package/dist/cjs/src/cluster/modules/AutoScaler.js +4 -4
- package/dist/cjs/src/cluster/modules/AutoScaler.js.map +1 -1
- package/dist/cjs/src/cluster/modules/CrossPlatformMemory.js +2 -2
- package/dist/cjs/src/cluster/modules/CrossPlatformMemory.js.map +1 -1
- package/dist/cjs/src/cluster/modules/EventLoopMonitor.js +270 -0
- package/dist/cjs/src/cluster/modules/EventLoopMonitor.js.map +1 -0
- package/dist/cjs/src/cluster/modules/GCStatsTracker.js +200 -0
- package/dist/cjs/src/cluster/modules/GCStatsTracker.js.map +1 -0
- package/dist/cjs/src/cluster/modules/HeapStatsCollector.js +111 -0
- package/dist/cjs/src/cluster/modules/HeapStatsCollector.js.map +1 -0
- package/dist/cjs/src/cluster/modules/NetworkTracker.js +162 -0
- package/dist/cjs/src/cluster/modules/NetworkTracker.js.map +1 -0
- package/dist/cjs/src/cluster/modules/ThroughputCalculator.js +186 -0
- package/dist/cjs/src/cluster/modules/ThroughputCalculator.js.map +1 -0
- package/dist/cjs/src/cluster/modules/WorkerManager.js +14 -15
- package/dist/cjs/src/cluster/modules/WorkerManager.js.map +1 -1
- package/dist/cjs/src/cluster/modules/{LoadBalancer.js → strategy/LoadBalancer.js} +1 -1
- package/dist/cjs/src/cluster/modules/strategy/LoadBalancer.js.map +1 -0
- package/dist/cjs/src/index.js +55 -61
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/middleware/XyPrissMiddlewareAPI.js +281 -0
- package/dist/cjs/src/middleware/XyPrissMiddlewareAPI.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/index.js +325 -0
- package/dist/cjs/src/middleware/built-in/index.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/sqlInjection.js +335 -0
- package/dist/cjs/src/middleware/built-in/sqlInjection.js.map +1 -0
- package/dist/cjs/src/middleware/safe-json-middleware.js +1 -1
- package/dist/cjs/src/middleware/safe-json-middleware.js.map +1 -1
- package/dist/cjs/src/middleware/security-middleware.js +447 -332
- package/dist/cjs/src/middleware/security-middleware.js.map +1 -1
- package/dist/cjs/src/plugins/modules/builtin/ResponseTimePlugin.js +1 -1
- package/dist/cjs/src/plugins/modules/builtin/ResponseTimePlugin.js.map +1 -1
- package/dist/cjs/src/plugins/modules/index.js +9 -3
- package/dist/cjs/src/plugins/modules/index.js.map +1 -1
- package/dist/cjs/src/quick-start.js +0 -4
- package/dist/cjs/src/quick-start.js.map +1 -1
- package/dist/cjs/src/server/FastServer.js +94 -412
- package/dist/cjs/src/server/FastServer.js.map +1 -1
- package/dist/cjs/src/server/ServerFactory.js +69 -64
- package/dist/cjs/src/server/ServerFactory.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/ClusterManagerComponent.js +31 -5
- package/dist/cjs/src/server/components/fastapi/ClusterManagerComponent.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/PerformanceManager.js +1 -1
- package/dist/cjs/src/server/components/fastapi/PerformanceManager.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/RouteManager.js +0 -82
- package/dist/cjs/src/server/components/fastapi/RouteManager.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/WorkerPoolComponent.js +206 -0
- package/dist/cjs/src/server/components/fastapi/WorkerPoolComponent.js.map +1 -0
- package/dist/cjs/src/server/components/fastapi/console/ConsoleInterceptor.js +3 -28
- package/dist/cjs/src/server/components/fastapi/console/ConsoleInterceptor.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/modules/UFRP/WorkerPoolManager.js +265 -0
- package/dist/cjs/src/server/components/fastapi/modules/UFRP/WorkerPoolManager.js.map +1 -0
- package/dist/cjs/src/server/components/fastapi/modules/UFRP/workers/Logger.js +236 -0
- package/dist/cjs/src/server/components/fastapi/modules/UFRP/workers/cpu-tasks.js +294 -0
- package/dist/cjs/src/server/components/fastapi/modules/UFRP/workers/enhanced-cpu-worker.js +433 -0
- package/dist/cjs/src/server/components/fastapi/modules/UFRP/workers/io-worker.js +1615 -0
- package/dist/cjs/src/server/components/lifecycle/ServerLifecycleManager.js +503 -0
- package/dist/cjs/src/server/components/lifecycle/ServerLifecycleManager.js.map +1 -0
- package/dist/cjs/src/server/const/default.js +23 -17
- package/dist/cjs/src/server/const/default.js.map +1 -1
- package/dist/cjs/src/server/core/HttpServer.js +500 -0
- package/dist/cjs/src/server/core/HttpServer.js.map +1 -0
- package/dist/cjs/src/server/core/XyprissApp.js +679 -0
- package/dist/cjs/src/server/core/XyprissApp.js.map +1 -0
- package/dist/cjs/src/server/handlers/NotFoundHandler.js +1 -1
- package/dist/cjs/src/server/handlers/NotFoundHandler.js.map +1 -1
- package/dist/cjs/src/server/middleware/MiddlewareManager.js +191 -0
- package/dist/cjs/src/server/middleware/MiddlewareManager.js.map +1 -0
- package/dist/cjs/src/server/routing/Router.js +341 -0
- package/dist/cjs/src/server/routing/Router.js.map +1 -0
- package/dist/cjs/src/server/utils/PortManager.js +1 -0
- package/dist/cjs/src/server/utils/PortManager.js.map +1 -1
- package/dist/cjs/src/server/utils/forceClosePort.js +294 -88
- package/dist/cjs/src/server/utils/forceClosePort.js.map +1 -1
- package/dist/esm/mods/security/src/algorithms/hash-algorithms.js +10 -0
- package/dist/esm/mods/security/src/algorithms/hash-algorithms.js.map +1 -1
- package/dist/esm/mods/security/src/components/cache/cacheSys.utils.js +10 -0
- package/dist/esm/mods/security/src/components/cache/cacheSys.utils.js.map +1 -1
- package/dist/esm/mods/security/src/components/cache/index.js +11 -72
- package/dist/esm/mods/security/src/components/cache/index.js.map +1 -1
- package/dist/esm/mods/security/src/components/fortified-function/index.js +9 -0
- package/dist/esm/mods/security/src/components/fortified-function/index.js.map +1 -1
- package/dist/esm/mods/security/src/components/fortified-function/security/security-handler.js +10 -0
- package/dist/esm/mods/security/src/components/fortified-function/security/security-handler.js.map +1 -1
- package/dist/esm/mods/security/src/core/crypto.js +14 -0
- package/dist/esm/mods/security/src/core/crypto.js.map +1 -1
- package/dist/esm/mods/security/src/index.js +11 -2
- package/dist/esm/mods/security/src/index.js.map +1 -1
- package/dist/esm/shared/logger/Logger.js +374 -29
- package/dist/esm/shared/logger/Logger.js.map +1 -1
- package/dist/esm/src/cluster/bun-cluster-manager.js +91 -1
- package/dist/esm/src/cluster/bun-cluster-manager.js.map +1 -1
- package/dist/esm/src/cluster/cluster-manager.js +15 -3
- package/dist/esm/src/cluster/cluster-manager.js.map +1 -1
- package/dist/esm/src/cluster/modules/AutoScaler.js +4 -4
- package/dist/esm/src/cluster/modules/AutoScaler.js.map +1 -1
- package/dist/esm/src/cluster/modules/CrossPlatformMemory.js +2 -2
- package/dist/esm/src/cluster/modules/CrossPlatformMemory.js.map +1 -1
- package/dist/esm/src/cluster/modules/EventLoopMonitor.js +268 -0
- package/dist/esm/src/cluster/modules/EventLoopMonitor.js.map +1 -0
- package/dist/esm/src/cluster/modules/GCStatsTracker.js +198 -0
- package/dist/esm/src/cluster/modules/GCStatsTracker.js.map +1 -0
- package/dist/esm/src/cluster/modules/HeapStatsCollector.js +109 -0
- package/dist/esm/src/cluster/modules/HeapStatsCollector.js.map +1 -0
- package/dist/esm/src/cluster/modules/NetworkTracker.js +160 -0
- package/dist/esm/src/cluster/modules/NetworkTracker.js.map +1 -0
- package/dist/esm/src/cluster/modules/ThroughputCalculator.js +184 -0
- package/dist/esm/src/cluster/modules/ThroughputCalculator.js.map +1 -0
- package/dist/esm/src/cluster/modules/WorkerManager.js +14 -14
- package/dist/esm/src/cluster/modules/WorkerManager.js.map +1 -1
- package/dist/esm/src/cluster/modules/{LoadBalancer.js → strategy/LoadBalancer.js} +1 -1
- package/dist/esm/src/cluster/modules/strategy/LoadBalancer.js.map +1 -0
- package/dist/esm/src/index.js +41 -11
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/middleware/XyPrissMiddlewareAPI.js +279 -0
- package/dist/esm/src/middleware/XyPrissMiddlewareAPI.js.map +1 -0
- package/dist/esm/src/middleware/built-in/index.js +323 -0
- package/dist/esm/src/middleware/built-in/index.js.map +1 -0
- package/dist/esm/src/middleware/built-in/sqlInjection.js +333 -0
- package/dist/esm/src/middleware/built-in/sqlInjection.js.map +1 -0
- package/dist/esm/src/middleware/safe-json-middleware.js +1 -1
- package/dist/esm/src/middleware/safe-json-middleware.js.map +1 -1
- package/dist/esm/src/middleware/security-middleware.js +447 -332
- package/dist/esm/src/middleware/security-middleware.js.map +1 -1
- package/dist/esm/src/plugins/modules/builtin/ResponseTimePlugin.js +1 -1
- package/dist/esm/src/plugins/modules/builtin/ResponseTimePlugin.js.map +1 -1
- package/dist/esm/src/plugins/modules/index.js +9 -3
- package/dist/esm/src/plugins/modules/index.js.map +1 -1
- package/dist/esm/src/quick-start.js +0 -4
- package/dist/esm/src/quick-start.js.map +1 -1
- package/dist/esm/src/server/FastServer.js +94 -412
- package/dist/esm/src/server/FastServer.js.map +1 -1
- package/dist/esm/src/server/ServerFactory.js +70 -61
- package/dist/esm/src/server/ServerFactory.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/ClusterManagerComponent.js +31 -5
- package/dist/esm/src/server/components/fastapi/ClusterManagerComponent.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/PerformanceManager.js +1 -1
- package/dist/esm/src/server/components/fastapi/PerformanceManager.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/RouteManager.js +0 -82
- package/dist/esm/src/server/components/fastapi/RouteManager.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/WorkerPoolComponent.js +204 -0
- package/dist/esm/src/server/components/fastapi/WorkerPoolComponent.js.map +1 -0
- package/dist/esm/src/server/components/fastapi/console/ConsoleInterceptor.js +2 -27
- package/dist/esm/src/server/components/fastapi/console/ConsoleInterceptor.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/modules/UFRP/WorkerPoolManager.js +263 -0
- package/dist/esm/src/server/components/fastapi/modules/UFRP/WorkerPoolManager.js.map +1 -0
- package/dist/esm/src/server/components/fastapi/modules/UFRP/workers/Logger.js +236 -0
- package/dist/esm/src/server/components/fastapi/modules/UFRP/workers/cpu-tasks.js +294 -0
- package/dist/esm/src/server/components/fastapi/modules/UFRP/workers/enhanced-cpu-worker.js +433 -0
- package/dist/esm/src/server/components/fastapi/modules/UFRP/workers/io-worker.js +1615 -0
- package/dist/esm/src/server/components/lifecycle/ServerLifecycleManager.js +501 -0
- package/dist/esm/src/server/components/lifecycle/ServerLifecycleManager.js.map +1 -0
- package/dist/esm/src/server/const/default.js +23 -17
- package/dist/esm/src/server/const/default.js.map +1 -1
- package/dist/esm/src/server/core/HttpServer.js +498 -0
- package/dist/esm/src/server/core/HttpServer.js.map +1 -0
- package/dist/esm/src/server/core/XyprissApp.js +677 -0
- package/dist/esm/src/server/core/XyprissApp.js.map +1 -0
- package/dist/esm/src/server/handlers/NotFoundHandler.js +1 -1
- package/dist/esm/src/server/handlers/NotFoundHandler.js.map +1 -1
- package/dist/esm/src/server/middleware/MiddlewareManager.js +189 -0
- package/dist/esm/src/server/middleware/MiddlewareManager.js.map +1 -0
- package/dist/esm/src/server/routing/Router.js +339 -0
- package/dist/esm/src/server/routing/Router.js.map +1 -0
- package/dist/esm/src/server/utils/PortManager.js +1 -0
- package/dist/esm/src/server/utils/PortManager.js.map +1 -1
- package/dist/esm/src/server/utils/forceClosePort.js +294 -88
- package/dist/esm/src/server/utils/forceClosePort.js.map +1 -1
- package/dist/index.d.ts +3363 -5311
- package/package.json +39 -28
- package/dist/cjs/src/cluster/index.js +0 -361
- package/dist/cjs/src/cluster/index.js.map +0 -1
- package/dist/cjs/src/cluster/modules/ClusterFactory.js +0 -539
- package/dist/cjs/src/cluster/modules/ClusterFactory.js.map +0 -1
- package/dist/cjs/src/cluster/modules/LoadBalancer.js.map +0 -1
- package/dist/cjs/src/server/components/fastapi/UltraFastRequestProcessor.js +0 -668
- package/dist/cjs/src/server/components/fastapi/UltraFastRequestProcessor.js.map +0 -1
- package/dist/cjs/src/server/components/fastapi/middlewares/MiddlewareAPI.js +0 -347
- package/dist/cjs/src/server/components/fastapi/middlewares/MiddlewareAPI.js.map +0 -1
- package/dist/cjs/src/server/components/fastapi/middlewares/MiddlewareMethodsManager.js +0 -204
- package/dist/cjs/src/server/components/fastapi/middlewares/MiddlewareMethodsManager.js.map +0 -1
- package/dist/cjs/src/server/components/fastapi/middlewares/middlewareManager.js +0 -953
- package/dist/cjs/src/server/components/fastapi/middlewares/middlewareManager.js.map +0 -1
- package/dist/cjs/src/server/components/fastapi/modules/UFRP/WorkerPool.js +0 -56
- package/dist/cjs/src/server/components/fastapi/modules/UFRP/WorkerPool.js.map +0 -1
- package/dist/esm/src/cluster/index.js +0 -339
- package/dist/esm/src/cluster/index.js.map +0 -1
- package/dist/esm/src/cluster/modules/ClusterFactory.js +0 -511
- package/dist/esm/src/cluster/modules/ClusterFactory.js.map +0 -1
- package/dist/esm/src/cluster/modules/LoadBalancer.js.map +0 -1
- package/dist/esm/src/server/components/fastapi/UltraFastRequestProcessor.js +0 -647
- package/dist/esm/src/server/components/fastapi/UltraFastRequestProcessor.js.map +0 -1
- package/dist/esm/src/server/components/fastapi/middlewares/MiddlewareAPI.js +0 -345
- package/dist/esm/src/server/components/fastapi/middlewares/MiddlewareAPI.js.map +0 -1
- package/dist/esm/src/server/components/fastapi/middlewares/MiddlewareMethodsManager.js +0 -202
- package/dist/esm/src/server/components/fastapi/middlewares/MiddlewareMethodsManager.js.map +0 -1
- package/dist/esm/src/server/components/fastapi/middlewares/middlewareManager.js +0 -951
- package/dist/esm/src/server/components/fastapi/middlewares/middlewareManager.js.map +0 -1
- package/dist/esm/src/server/components/fastapi/modules/UFRP/WorkerPool.js +0 -54
- package/dist/esm/src/server/components/fastapi/modules/UFRP/WorkerPool.js.map +0 -1
|
@@ -1,413 +1,528 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
require('
|
|
6
|
-
require('
|
|
7
|
-
require('
|
|
8
|
-
require('
|
|
9
|
-
require('
|
|
10
|
-
require('
|
|
11
|
-
require('
|
|
12
|
-
require('
|
|
13
|
-
require('
|
|
14
|
-
require('../../mods/security/src/utils/memory/index.js');
|
|
15
|
-
require('../../mods/security/src/types.js');
|
|
16
|
-
require('../../mods/security/src/types/secure-memory.js');
|
|
17
|
-
require('../../mods/security/src/components/secure-string/advanced/entropy-analyzer.js');
|
|
18
|
-
require('../../mods/security/src/components/secure-string/advanced/quantum-safe.js');
|
|
19
|
-
require('../../mods/security/src/components/secure-string/advanced/performance-monitor.js');
|
|
20
|
-
require('nehoid');
|
|
3
|
+
var helmet = require('helmet');
|
|
4
|
+
var cors = require('cors');
|
|
5
|
+
var rateLimit = require('express-rate-limit');
|
|
6
|
+
var csrfCsrf = require('csrf-csrf');
|
|
7
|
+
var mongoSanitize = require('express-mongo-sanitize');
|
|
8
|
+
var xss = require('xss');
|
|
9
|
+
var hpp = require('hpp');
|
|
10
|
+
var compression = require('compression');
|
|
11
|
+
var xyprissSecurity = require('xypriss-security');
|
|
12
|
+
var sqlInjection = require('./built-in/sqlInjection.js');
|
|
13
|
+
var Logger = require('../../shared/logger/Logger.js');
|
|
21
14
|
|
|
22
15
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
16
|
+
* XyPriss Security Middleware
|
|
17
|
+
* Comprehensive security middleware using proven external libraries
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Security middleware class implementing comprehensive protection
|
|
21
|
+
* Implements SecurityConfig interface to ensure type safety
|
|
25
22
|
*/
|
|
26
23
|
class SecurityMiddleware {
|
|
27
|
-
constructor(config = {}) {
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
24
|
+
constructor(config = {}, logger) {
|
|
25
|
+
// Initialize logger (create default if not provided)
|
|
26
|
+
this.logger =
|
|
27
|
+
logger ||
|
|
28
|
+
new Logger.Logger({
|
|
29
|
+
enabled: true,
|
|
30
|
+
level: "debug",
|
|
31
|
+
components: { security: true },
|
|
32
|
+
types: { debug: true },
|
|
33
|
+
});
|
|
34
|
+
// Set defaults and merge with provided config
|
|
35
|
+
this.level = config.level || "enhanced";
|
|
36
|
+
this.csrf = config.csrf !== false;
|
|
37
|
+
this.helmet = config.helmet !== false;
|
|
38
|
+
this.xss = config.xss !== false;
|
|
39
|
+
this.sqlInjection = config.sqlInjection !== false;
|
|
40
|
+
this.bruteForce = config.bruteForce !== false;
|
|
41
|
+
this.encryption = {
|
|
42
|
+
algorithm: "AES-256-GCM",
|
|
43
|
+
keySize: 32,
|
|
44
|
+
...config.encryption,
|
|
45
|
+
};
|
|
46
|
+
this.authentication = {
|
|
47
|
+
jwt: {
|
|
48
|
+
secret: config.authentication?.jwt?.secret ||
|
|
49
|
+
xyprissSecurity.XyPrissSecurity.generateSecureToken({
|
|
43
50
|
length: 32,
|
|
44
51
|
entropy: "high",
|
|
45
52
|
}),
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
expiresIn: config.authentication?.jwt?.expiresIn || "1h",
|
|
54
|
+
algorithm: config.authentication?.jwt?.algorithm || "HS256",
|
|
55
|
+
},
|
|
56
|
+
session: {
|
|
57
|
+
secret: config.authentication?.session?.secret ||
|
|
58
|
+
xyprissSecurity.XyPrissSecurity.generateSecureToken({
|
|
51
59
|
length: 32,
|
|
52
60
|
entropy: "high",
|
|
53
61
|
}),
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
name: config.authentication?.session?.name ||
|
|
63
|
+
"nehonix.XyPriss.sid",
|
|
64
|
+
cookie: {
|
|
65
|
+
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
|
66
|
+
secure: true,
|
|
67
|
+
httpOnly: true,
|
|
68
|
+
sameSite: "strict",
|
|
69
|
+
...config.authentication?.session?.cookie,
|
|
61
70
|
},
|
|
62
71
|
},
|
|
63
|
-
...config,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Get the main security middleware
|
|
68
|
-
*/
|
|
69
|
-
getMiddleware() {
|
|
70
|
-
return (req, res, next) => {
|
|
71
|
-
// Apply security measures based on level
|
|
72
|
-
this.applySecurityHeaders(req, res);
|
|
73
|
-
this.checkBruteForce(req, res, next);
|
|
72
|
+
...config.authentication,
|
|
74
73
|
};
|
|
74
|
+
// Initialize security detectors
|
|
75
|
+
this.sqlInjectionDetector = new sqlInjection({
|
|
76
|
+
strictMode: false,
|
|
77
|
+
contextualAnalysis: true,
|
|
78
|
+
logAttempts: true,
|
|
79
|
+
falsePositiveThreshold: 0.6,
|
|
80
|
+
});
|
|
81
|
+
// Initialize all middleware instances
|
|
82
|
+
this.initializeMiddleware();
|
|
75
83
|
}
|
|
76
84
|
/**
|
|
77
|
-
*
|
|
85
|
+
* Initialize all security middleware instances using external libraries
|
|
78
86
|
*/
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
initializeMiddleware() {
|
|
88
|
+
// Helmet for security headers
|
|
89
|
+
if (this.helmet) {
|
|
90
|
+
this.helmetMiddleware = helmet({
|
|
91
|
+
contentSecurityPolicy: this.level === "maximum"
|
|
92
|
+
? {
|
|
93
|
+
directives: {
|
|
94
|
+
defaultSrc: ["'self'"],
|
|
95
|
+
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
96
|
+
scriptSrc: ["'self'"],
|
|
97
|
+
imgSrc: ["'self'", "data:", "https:"],
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
: false,
|
|
101
|
+
hsts: this.level !== "basic",
|
|
102
|
+
crossOriginEmbedderPolicy: this.level === "maximum",
|
|
90
103
|
});
|
|
91
104
|
}
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const maxAttempts = 10;
|
|
120
|
-
const windowMs = 15 * 60 * 1000; // 15 minutes
|
|
121
|
-
const blockDuration = 60 * 60 * 1000; // 1 hour
|
|
122
|
-
let record = this.bruteForceMap.get(ip);
|
|
123
|
-
if (!record) {
|
|
124
|
-
record = { attempts: 0, lastAttempt: now };
|
|
125
|
-
this.bruteForceMap.set(ip, record);
|
|
105
|
+
// CORS middleware
|
|
106
|
+
this.corsMiddleware = cors({
|
|
107
|
+
origin: this.level === "maximum" ? false : true,
|
|
108
|
+
credentials: true,
|
|
109
|
+
optionsSuccessStatus: 200,
|
|
110
|
+
});
|
|
111
|
+
// Rate limiting for brute force protection
|
|
112
|
+
if (this.bruteForce) {
|
|
113
|
+
const maxRequests = this.level === "maximum"
|
|
114
|
+
? 50
|
|
115
|
+
: this.level === "enhanced"
|
|
116
|
+
? 100
|
|
117
|
+
: 200;
|
|
118
|
+
this.rateLimitMiddleware = rateLimit({
|
|
119
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
120
|
+
max: maxRequests,
|
|
121
|
+
message: {
|
|
122
|
+
error: "Too many requests from this IP, please try again later.",
|
|
123
|
+
retryAfter: "15 minutes",
|
|
124
|
+
},
|
|
125
|
+
standardHeaders: true,
|
|
126
|
+
legacyHeaders: false,
|
|
127
|
+
skip: (req) => {
|
|
128
|
+
// Skip rate limiting for health checks
|
|
129
|
+
return req.path === "/health" || req.path === "/ping";
|
|
130
|
+
},
|
|
131
|
+
});
|
|
126
132
|
}
|
|
127
|
-
//
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
// CSRF protection using csrf-csrf library
|
|
134
|
+
if (this.csrf) {
|
|
135
|
+
const { doubleCsrfProtection } = csrfCsrf.doubleCsrf({
|
|
136
|
+
getSecret: () => this.authentication.session?.secret || "default-secret",
|
|
137
|
+
getSessionIdentifier: (req) => req.sessionID || req.ip || "anonymous",
|
|
138
|
+
cookieName: "__Host-csrf-token",
|
|
139
|
+
cookieOptions: {
|
|
140
|
+
httpOnly: true,
|
|
141
|
+
sameSite: "strict",
|
|
142
|
+
secure: process.env.NODE_ENV === "production",
|
|
143
|
+
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
|
144
|
+
},
|
|
145
|
+
size: 64,
|
|
146
|
+
ignoredMethods: ["GET", "HEAD", "OPTIONS"],
|
|
132
147
|
});
|
|
148
|
+
// Create a wrapper that ensures cookies exist
|
|
149
|
+
this.csrfMiddleware = (req, res, next) => {
|
|
150
|
+
// Ensure cookies object exists for Express compatibility
|
|
151
|
+
if (!req.cookies) {
|
|
152
|
+
req.cookies = {};
|
|
153
|
+
}
|
|
154
|
+
// Call the original CSRF middleware
|
|
155
|
+
doubleCsrfProtection(req, res, next);
|
|
156
|
+
};
|
|
133
157
|
}
|
|
134
|
-
//
|
|
135
|
-
if (
|
|
136
|
-
|
|
158
|
+
// MongoDB injection protection
|
|
159
|
+
if (this.sqlInjection) {
|
|
160
|
+
const originalMongoSanitize = mongoSanitize({
|
|
161
|
+
replaceWith: "_",
|
|
162
|
+
onSanitize: ({ req, key }) => {
|
|
163
|
+
console.warn(`Sanitized key ${key} in request from ${req.ip}`);
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
// Create a wrapper that handles readonly properties
|
|
167
|
+
this.mongoSanitizeMiddleware = (req, res, next) => {
|
|
168
|
+
// Make request properties writable before sanitization
|
|
169
|
+
this.makeRequestPropertiesWritable(req);
|
|
170
|
+
// Call the original middleware
|
|
171
|
+
originalMongoSanitize(req, res, next);
|
|
172
|
+
};
|
|
137
173
|
}
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
174
|
+
// HTTP Parameter Pollution protection
|
|
175
|
+
const originalHpp = hpp({
|
|
176
|
+
whitelist: ["tags", "categories"], // Allow arrays for specific parameters
|
|
177
|
+
});
|
|
178
|
+
// Create a wrapper that handles readonly properties
|
|
179
|
+
this.hppMiddleware = (req, res, next) => {
|
|
180
|
+
// Make request properties writable before processing
|
|
181
|
+
this.makeRequestPropertiesWritable(req);
|
|
182
|
+
// Call the original middleware
|
|
183
|
+
originalHpp(req, res, next);
|
|
184
|
+
};
|
|
185
|
+
// Compression middleware
|
|
186
|
+
this.compressionMiddleware = compression({
|
|
187
|
+
filter: (req, res) => {
|
|
188
|
+
if (req.headers["x-no-compression"]) {
|
|
189
|
+
return false;
|
|
146
190
|
}
|
|
147
|
-
|
|
191
|
+
return compression.filter(req, res);
|
|
192
|
+
},
|
|
193
|
+
level: 6,
|
|
194
|
+
threshold: 1024,
|
|
148
195
|
});
|
|
149
|
-
next();
|
|
150
196
|
}
|
|
151
197
|
/**
|
|
152
|
-
*
|
|
198
|
+
* Get the main security middleware stack
|
|
199
|
+
* Returns a single middleware function that applies all security measures
|
|
153
200
|
*/
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
// Check for excessive hex encoding
|
|
161
|
-
const hexCount = (input.match(/\\x[0-9a-f]{2}/gi) || []).length;
|
|
162
|
-
if (hexCount > 3) {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
// Check for suspicious character sequences
|
|
166
|
-
const suspiciousPatterns = [
|
|
167
|
-
/(\+|\s)(and|or)(\+|\s)/gi,
|
|
168
|
-
/[0-9]+\s*[=<>]\s*[0-9]+/gi,
|
|
169
|
-
/(char|ascii)\s*\(\s*[0-9]+/gi,
|
|
170
|
-
/concat\s*\(/gi,
|
|
171
|
-
];
|
|
172
|
-
return suspiciousPatterns.some((pattern) => pattern.test(input));
|
|
201
|
+
getMiddleware() {
|
|
202
|
+
return (req, res, next) => {
|
|
203
|
+
this.applySecurityStack(req, res, next);
|
|
204
|
+
};
|
|
173
205
|
}
|
|
174
206
|
/**
|
|
175
|
-
*
|
|
207
|
+
* Apply all security middleware in the correct order
|
|
176
208
|
*/
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
209
|
+
applySecurityStack(req, res, next) {
|
|
210
|
+
this.logger.debug("security", "Starting security middleware stack");
|
|
211
|
+
const middlewareStack = [];
|
|
212
|
+
// 1. Compression (should be first)
|
|
213
|
+
this.logger.debug("security", "Adding compression middleware");
|
|
214
|
+
middlewareStack.push(this.compressionMiddleware);
|
|
215
|
+
// 2. Security headers (Helmet)
|
|
216
|
+
if (this.helmet && this.helmetMiddleware) {
|
|
217
|
+
this.logger.debug("security", "Adding helmet middleware");
|
|
218
|
+
middlewareStack.push(this.helmetMiddleware);
|
|
219
|
+
}
|
|
220
|
+
// 3. CORS
|
|
221
|
+
this.logger.debug("security", "Adding CORS middleware");
|
|
222
|
+
middlewareStack.push(this.corsMiddleware);
|
|
223
|
+
// 4. Rate limiting
|
|
224
|
+
if (this.bruteForce && this.rateLimitMiddleware) {
|
|
225
|
+
this.logger.debug("security", "Adding rate limit middleware");
|
|
226
|
+
middlewareStack.push(this.rateLimitMiddleware);
|
|
227
|
+
}
|
|
228
|
+
// 5. HTTP Parameter Pollution protection
|
|
229
|
+
this.logger.debug("security", "Adding HPP middleware");
|
|
230
|
+
middlewareStack.push(this.hppMiddleware);
|
|
231
|
+
// 6. MongoDB sanitization
|
|
232
|
+
if (this.sqlInjection && this.mongoSanitizeMiddleware) {
|
|
233
|
+
this.logger.debug("security", "Adding mongo sanitize middleware");
|
|
234
|
+
middlewareStack.push(this.mongoSanitizeMiddleware);
|
|
235
|
+
}
|
|
236
|
+
// 7. XSS protection (custom implementation)
|
|
237
|
+
if (this.xss) {
|
|
238
|
+
this.logger.debug("security", "Adding XSS protection middleware");
|
|
239
|
+
middlewareStack.push(this.xssProtection.bind(this));
|
|
240
|
+
}
|
|
241
|
+
// 8. CSRF protection (should be after body parsing)
|
|
242
|
+
if (this.csrf && this.csrfMiddleware) {
|
|
243
|
+
this.logger.debug("security", "Adding CSRF middleware");
|
|
244
|
+
middlewareStack.push(this.csrfMiddleware);
|
|
245
|
+
}
|
|
246
|
+
this.logger.debug("security", `Total middleware in stack: ${middlewareStack.length}`);
|
|
247
|
+
// Execute middleware stack
|
|
248
|
+
this.executeMiddlewareStack(middlewareStack, req, res, next);
|
|
184
249
|
}
|
|
185
250
|
/**
|
|
186
|
-
*
|
|
251
|
+
* Execute middleware stack sequentially with proper async handling
|
|
187
252
|
*/
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
253
|
+
executeMiddlewareStack(stack, req, res, finalNext) {
|
|
254
|
+
let index = 0;
|
|
255
|
+
let nextCalled = false;
|
|
256
|
+
this.logger.debug("security", `Executing middleware stack with ${stack.length} middleware`);
|
|
257
|
+
const next = (error) => {
|
|
258
|
+
if (nextCalled) {
|
|
259
|
+
this.logger.debug("security", "next() already called, ignoring duplicate call");
|
|
260
|
+
return;
|
|
192
261
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
next();
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* SQL Injection protection middleware
|
|
202
|
-
*/
|
|
203
|
-
sqlInjectionProtection() {
|
|
204
|
-
return (req, res, next) => {
|
|
205
|
-
if (!this.config.sqlInjection) {
|
|
206
|
-
return next();
|
|
262
|
+
if (error) {
|
|
263
|
+
nextCalled = true;
|
|
264
|
+
this.logger.debug("security", `Error in middleware at index ${index - 1}:`, error);
|
|
265
|
+
return finalNext(error);
|
|
207
266
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
];
|
|
227
|
-
const validateSQLInput = (obj, path = "") => {
|
|
228
|
-
if (typeof obj === "string") {
|
|
229
|
-
// Use XyPrissJS pattern matching for enhanced detection
|
|
230
|
-
const normalizedInput = obj
|
|
231
|
-
.toLowerCase()
|
|
232
|
-
.replace(/\s+/g, " ")
|
|
233
|
-
.trim();
|
|
234
|
-
// Check against SQL injection patterns
|
|
235
|
-
for (const pattern of sqlPatterns) {
|
|
236
|
-
if (pattern.test(normalizedInput)) {
|
|
237
|
-
console.warn(` SQL injection pattern detected in ${path}: ${pattern.source}`);
|
|
238
|
-
return true;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// Additional entropy-based detection for obfuscated attacks
|
|
242
|
-
if (this.detectObfuscatedSQLInjection(normalizedInput)) {
|
|
243
|
-
console.warn(` Obfuscated SQL injection detected in ${path}`);
|
|
244
|
-
return true;
|
|
267
|
+
if (index >= stack.length) {
|
|
268
|
+
nextCalled = true;
|
|
269
|
+
this.logger.debug("security", "All middleware completed, calling final next");
|
|
270
|
+
return finalNext();
|
|
271
|
+
}
|
|
272
|
+
const currentIndex = index;
|
|
273
|
+
this.logger.debug("security", `Executing middleware ${currentIndex + 1}/${stack.length}`);
|
|
274
|
+
const middleware = stack[index++];
|
|
275
|
+
try {
|
|
276
|
+
// Set a timeout to detect if middleware doesn't call next()
|
|
277
|
+
let timeoutId = null;
|
|
278
|
+
let middlewareCompleted = false;
|
|
279
|
+
const middlewareNext = (err) => {
|
|
280
|
+
if (middlewareCompleted)
|
|
281
|
+
return;
|
|
282
|
+
middlewareCompleted = true;
|
|
283
|
+
if (timeoutId) {
|
|
284
|
+
clearTimeout(timeoutId);
|
|
245
285
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
286
|
+
this.logger.debug("security", `Middleware ${currentIndex + 1} completed`);
|
|
287
|
+
next(err);
|
|
288
|
+
};
|
|
289
|
+
// Set timeout to detect hanging middleware
|
|
290
|
+
timeoutId = setTimeout(() => {
|
|
291
|
+
if (!middlewareCompleted) {
|
|
292
|
+
this.logger.debug("security", `Middleware ${currentIndex + 1} timed out, continuing anyway`);
|
|
293
|
+
middlewareCompleted = true;
|
|
294
|
+
next();
|
|
253
295
|
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return res.status(400).json({
|
|
262
|
-
error: "Invalid input detected",
|
|
263
|
-
});
|
|
296
|
+
}, 100); // 100ms timeout
|
|
297
|
+
// Execute the middleware
|
|
298
|
+
middleware(req, res, middlewareNext);
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
this.logger.debug("security", `Exception in middleware at index ${currentIndex}:`, error);
|
|
302
|
+
finalNext(error);
|
|
264
303
|
}
|
|
265
|
-
next();
|
|
266
304
|
};
|
|
305
|
+
// Start the middleware chain
|
|
306
|
+
this.logger.debug("security", "Starting middleware chain");
|
|
307
|
+
next();
|
|
267
308
|
}
|
|
268
309
|
/**
|
|
269
|
-
*
|
|
310
|
+
* Custom XSS protection middleware
|
|
270
311
|
*/
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
312
|
+
xssProtection(req, res, next) {
|
|
313
|
+
let maliciousContentDetected = false;
|
|
314
|
+
const detectedThreats = [];
|
|
315
|
+
// Check and sanitize request body
|
|
316
|
+
if (req.body && typeof req.body === "object") {
|
|
317
|
+
const { sanitized, threats } = this.sanitizeObjectWithDetection(req.body);
|
|
318
|
+
if (threats.length > 0) {
|
|
319
|
+
maliciousContentDetected = true;
|
|
320
|
+
detectedThreats.push(...threats.map((t) => `body.${t}`));
|
|
275
321
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
return next();
|
|
322
|
+
try {
|
|
323
|
+
req.body = sanitized;
|
|
279
324
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
req
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
!crypto.XyPrissSecurity.constantTimeEqual(token, sessionToken)) {
|
|
287
|
-
return res.status(403).json({
|
|
288
|
-
error: "CSRF token validation failed",
|
|
325
|
+
catch (error) {
|
|
326
|
+
// Handle readonly property - create new object
|
|
327
|
+
Object.defineProperty(req, "body", {
|
|
328
|
+
value: sanitized,
|
|
329
|
+
writable: true,
|
|
330
|
+
configurable: true,
|
|
289
331
|
});
|
|
290
332
|
}
|
|
291
|
-
|
|
292
|
-
|
|
333
|
+
}
|
|
334
|
+
// Check and sanitize query parameters
|
|
335
|
+
if (req.query && typeof req.query === "object") {
|
|
336
|
+
const { sanitized, threats } = this.sanitizeObjectWithDetection(req.query);
|
|
337
|
+
if (threats.length > 0) {
|
|
338
|
+
maliciousContentDetected = true;
|
|
339
|
+
detectedThreats.push(...threats.map((t) => `query.${t}`));
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
req.query = sanitized;
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
// Handle readonly property - create new object
|
|
346
|
+
Object.defineProperty(req, "query", {
|
|
347
|
+
value: sanitized,
|
|
348
|
+
writable: true,
|
|
349
|
+
configurable: true,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// Check and sanitize URL parameters
|
|
354
|
+
if (req.params && typeof req.params === "object") {
|
|
355
|
+
const { sanitized, threats } = this.sanitizeObjectWithDetection(req.params);
|
|
356
|
+
if (threats.length > 0) {
|
|
357
|
+
maliciousContentDetected = true;
|
|
358
|
+
detectedThreats.push(...threats.map((t) => `params.${t}`));
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
req.params = sanitized;
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
// Handle readonly property - create new object
|
|
365
|
+
Object.defineProperty(req, "params", {
|
|
366
|
+
value: sanitized,
|
|
367
|
+
writable: true,
|
|
368
|
+
configurable: true,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// Block request if malicious content was detected
|
|
373
|
+
if (maliciousContentDetected) {
|
|
374
|
+
this.logger.warn("security", `XSS attack blocked from ${req.ip}. Threats detected: ${detectedThreats.join(", ")}`);
|
|
375
|
+
res.status(400).json({
|
|
376
|
+
error: "Malicious content detected",
|
|
377
|
+
message: "Request blocked due to potential XSS attack",
|
|
378
|
+
threats: detectedThreats,
|
|
379
|
+
timestamp: new Date().toISOString(),
|
|
380
|
+
});
|
|
381
|
+
return; // Don't call next() - block the request
|
|
382
|
+
}
|
|
383
|
+
next();
|
|
293
384
|
}
|
|
294
385
|
/**
|
|
295
|
-
*
|
|
386
|
+
* Make request properties writable to avoid readonly property errors
|
|
296
387
|
*/
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
if (
|
|
301
|
-
return next();
|
|
302
|
-
}
|
|
303
|
-
// Check if request is encrypted
|
|
304
|
-
const encryptedHeader = req.headers["x-encrypted-request"];
|
|
305
|
-
if (encryptedHeader && req.body) {
|
|
388
|
+
makeRequestPropertiesWritable(req) {
|
|
389
|
+
const properties = ["body", "params", "headers", "query"];
|
|
390
|
+
properties.forEach((prop) => {
|
|
391
|
+
if (req[prop] !== undefined) {
|
|
306
392
|
try {
|
|
307
|
-
//
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
secureObj.setEncryptionKey(self.config.authentication?.jwt?.secret || "default-key");
|
|
311
|
-
const decryptedData = secureObj.toObject();
|
|
312
|
-
req.body = JSON.parse(decryptedData.data);
|
|
393
|
+
// Test if property is writable
|
|
394
|
+
const original = req[prop];
|
|
395
|
+
req[prop] = original;
|
|
313
396
|
}
|
|
314
397
|
catch (error) {
|
|
315
|
-
|
|
316
|
-
|
|
398
|
+
// Property is readonly, make it writable
|
|
399
|
+
const value = req[prop];
|
|
400
|
+
Object.defineProperty(req, prop, {
|
|
401
|
+
value: value,
|
|
402
|
+
writable: true,
|
|
403
|
+
configurable: true,
|
|
404
|
+
enumerable: true,
|
|
317
405
|
});
|
|
318
406
|
}
|
|
319
407
|
}
|
|
320
|
-
|
|
321
|
-
const originalJson = res.json;
|
|
322
|
-
res.json = function (data) {
|
|
323
|
-
if (req.headers["x-encrypt-response"]) {
|
|
324
|
-
// Encryption using SecureObject
|
|
325
|
-
const secureObj = new secureObjectCore.SecureObject({
|
|
326
|
-
data: JSON.stringify(data),
|
|
327
|
-
});
|
|
328
|
-
secureObj.setEncryptionKey(self.config.authentication?.jwt?.secret || "default-key");
|
|
329
|
-
secureObj.encryptAll();
|
|
330
|
-
const encrypted = secureObj.exportData();
|
|
331
|
-
res.set("X-Encrypted-Response", "true");
|
|
332
|
-
return originalJson.call(this, { data: encrypted });
|
|
333
|
-
}
|
|
334
|
-
return originalJson.call(this, data);
|
|
335
|
-
};
|
|
336
|
-
next();
|
|
337
|
-
};
|
|
408
|
+
});
|
|
338
409
|
}
|
|
339
410
|
/**
|
|
340
|
-
*
|
|
411
|
+
* Recursively sanitize object properties
|
|
341
412
|
*/
|
|
342
413
|
sanitizeObject(obj) {
|
|
343
414
|
if (typeof obj === "string") {
|
|
344
|
-
return
|
|
415
|
+
return xss(obj);
|
|
345
416
|
}
|
|
346
|
-
if (
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
417
|
+
if (Array.isArray(obj)) {
|
|
418
|
+
return obj.map((item) => this.sanitizeObject(item));
|
|
419
|
+
}
|
|
420
|
+
if (obj && typeof obj === "object") {
|
|
421
|
+
const sanitized = {};
|
|
422
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
423
|
+
sanitized[key] = this.sanitizeObject(value);
|
|
351
424
|
}
|
|
425
|
+
return sanitized;
|
|
352
426
|
}
|
|
353
427
|
return obj;
|
|
354
428
|
}
|
|
355
429
|
/**
|
|
356
|
-
* Sanitize
|
|
357
|
-
*/
|
|
358
|
-
sanitizeString(str) {
|
|
359
|
-
return str
|
|
360
|
-
.replace(/</g, "<")
|
|
361
|
-
.replace(/>/g, ">")
|
|
362
|
-
.replace(/"/g, """)
|
|
363
|
-
.replace(/'/g, "'")
|
|
364
|
-
.replace(/\//g, "/")
|
|
365
|
-
.replace(/javascript:/gi, "")
|
|
366
|
-
.replace(/on\w+=/gi, "");
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Get security configuration
|
|
430
|
+
* Sanitize object and detect threats
|
|
370
431
|
*/
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
432
|
+
sanitizeObjectWithDetection(obj, path = "") {
|
|
433
|
+
const threats = [];
|
|
434
|
+
const sanitizeWithDetection = (value, currentPath) => {
|
|
435
|
+
if (typeof value === "string") {
|
|
436
|
+
const original = value;
|
|
437
|
+
let sanitized = xss(value);
|
|
438
|
+
let threatDetected = false;
|
|
439
|
+
const detectedPatterns = [];
|
|
440
|
+
// Check if XSS library sanitization changed the content
|
|
441
|
+
if (original !== sanitized) {
|
|
442
|
+
threatDetected = true;
|
|
443
|
+
detectedPatterns.push("XSS");
|
|
444
|
+
}
|
|
445
|
+
// SQL Injection Detection
|
|
446
|
+
if (this.sqlInjection) {
|
|
447
|
+
const sqlResult = this.sqlInjectionDetector.detect(original, currentPath);
|
|
448
|
+
if (sqlResult.isMalicious) {
|
|
449
|
+
threatDetected = true;
|
|
450
|
+
detectedPatterns.push(`SQL Injection (${sqlResult.riskLevel})`);
|
|
451
|
+
// Use the SQL detector's sanitized version if available
|
|
452
|
+
if (sqlResult.sanitizedInput) {
|
|
453
|
+
sanitized = sqlResult.sanitizedInput;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
// Additional threat detection for patterns XSS library might miss
|
|
458
|
+
const additionalThreats = [
|
|
459
|
+
/javascript:/i,
|
|
460
|
+
/vbscript:/i,
|
|
461
|
+
/data:/i,
|
|
462
|
+
/on\w+\s*=/i, // event handlers like onclick=, onload=
|
|
463
|
+
/<iframe/i,
|
|
464
|
+
/<object/i,
|
|
465
|
+
/<embed/i,
|
|
466
|
+
/<link/i,
|
|
467
|
+
/<meta/i,
|
|
468
|
+
/expression\s*\(/i, // CSS expression()
|
|
469
|
+
/url\s*\(\s*javascript:/i,
|
|
470
|
+
];
|
|
471
|
+
for (const pattern of additionalThreats) {
|
|
472
|
+
if (pattern.test(original)) {
|
|
473
|
+
threatDetected = true;
|
|
474
|
+
detectedPatterns.push("Enhanced XSS");
|
|
475
|
+
// Sanitize these additional threats
|
|
476
|
+
sanitized = original.replace(pattern, "[BLOCKED]");
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
if (threatDetected) {
|
|
481
|
+
threats.push(currentPath || "root");
|
|
482
|
+
// Log the specific threats detected
|
|
483
|
+
this.logger.warn("security", `Security threat detected in ${currentPath || "root"}: ${detectedPatterns.join(", ")}`);
|
|
484
|
+
}
|
|
485
|
+
return sanitized;
|
|
387
486
|
}
|
|
388
|
-
|
|
389
|
-
|
|
487
|
+
if (Array.isArray(value)) {
|
|
488
|
+
return value.map((item, index) => sanitizeWithDetection(item, `${currentPath}[${index}]`));
|
|
390
489
|
}
|
|
391
|
-
|
|
392
|
-
|
|
490
|
+
if (value && typeof value === "object") {
|
|
491
|
+
const sanitized = {};
|
|
492
|
+
for (const [key, val] of Object.entries(value)) {
|
|
493
|
+
const newPath = currentPath ? `${currentPath}.${key}` : key;
|
|
494
|
+
sanitized[key] = sanitizeWithDetection(val, newPath);
|
|
495
|
+
}
|
|
496
|
+
return sanitized;
|
|
497
|
+
}
|
|
498
|
+
return value;
|
|
499
|
+
};
|
|
500
|
+
const sanitized = sanitizeWithDetection(obj, path);
|
|
501
|
+
return { sanitized, threats };
|
|
393
502
|
}
|
|
394
503
|
/**
|
|
395
|
-
*
|
|
504
|
+
* Get CSRF token for client-side usage
|
|
396
505
|
*/
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
delete record.blockedUntil;
|
|
401
|
-
record.attempts = 0;
|
|
402
|
-
return true;
|
|
506
|
+
generateCsrfToken(req) {
|
|
507
|
+
if (this.csrf && req.csrfToken) {
|
|
508
|
+
return req.csrfToken();
|
|
403
509
|
}
|
|
404
|
-
return
|
|
510
|
+
return null;
|
|
405
511
|
}
|
|
406
512
|
/**
|
|
407
|
-
*
|
|
513
|
+
* Get security configuration
|
|
408
514
|
*/
|
|
409
|
-
|
|
410
|
-
|
|
515
|
+
getConfig() {
|
|
516
|
+
return {
|
|
517
|
+
level: this.level,
|
|
518
|
+
csrf: this.csrf,
|
|
519
|
+
helmet: this.helmet,
|
|
520
|
+
xss: this.xss,
|
|
521
|
+
sqlInjection: this.sqlInjection,
|
|
522
|
+
bruteForce: this.bruteForce,
|
|
523
|
+
encryption: this.encryption,
|
|
524
|
+
authentication: this.authentication,
|
|
525
|
+
};
|
|
411
526
|
}
|
|
412
527
|
}
|
|
413
528
|
|