xypriss 1.1.2 → 1.1.4
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 +13 -13
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/mods/security/src/index.js +35 -12
- package/dist/cjs/mods/security/src/index.js.map +1 -1
- package/dist/cjs/src/plugins/modules/PluginEngine.js +378 -0
- package/dist/cjs/src/plugins/modules/PluginEngine.js.map +1 -0
- package/dist/cjs/src/plugins/modules/PluginRegistry.js +339 -0
- package/dist/cjs/src/plugins/modules/PluginRegistry.js.map +1 -0
- package/dist/cjs/src/plugins/modules/builtin/JWTAuthPlugin.js +591 -0
- package/dist/cjs/src/plugins/modules/builtin/JWTAuthPlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/builtin/ResponseTimePlugin.js +413 -0
- package/dist/cjs/src/plugins/modules/builtin/ResponseTimePlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/builtin/SmartCachePlugin.js +843 -0
- package/dist/cjs/src/plugins/modules/builtin/SmartCachePlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/core/CachePlugin.js +1975 -0
- package/dist/cjs/src/plugins/modules/core/CachePlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/core/PerformancePlugin.js +894 -0
- package/dist/cjs/src/plugins/modules/core/PerformancePlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/core/SecurityPlugin.js +799 -0
- package/dist/cjs/src/plugins/modules/core/SecurityPlugin.js.map +1 -0
- package/dist/cjs/src/plugins/modules/types/PluginTypes.js +47 -0
- package/dist/cjs/src/plugins/modules/types/PluginTypes.js.map +1 -0
- package/dist/cjs/src/server/FastServer.js +22 -3
- package/dist/cjs/src/server/FastServer.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/PluginManager.js +5 -5
- package/dist/cjs/src/server/components/fastapi/PluginManager.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/RequestProcessor.js +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/mods/security/src/index.js +14 -10
- package/dist/esm/mods/security/src/index.js.map +1 -1
- package/dist/esm/src/plugins/modules/PluginEngine.js +376 -0
- package/dist/esm/src/plugins/modules/PluginEngine.js.map +1 -0
- package/dist/esm/src/plugins/modules/PluginRegistry.js +337 -0
- package/dist/esm/src/plugins/modules/PluginRegistry.js.map +1 -0
- package/dist/esm/src/plugins/modules/builtin/JWTAuthPlugin.js +589 -0
- package/dist/esm/src/plugins/modules/builtin/JWTAuthPlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/builtin/ResponseTimePlugin.js +411 -0
- package/dist/esm/src/plugins/modules/builtin/ResponseTimePlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/builtin/SmartCachePlugin.js +841 -0
- package/dist/esm/src/plugins/modules/builtin/SmartCachePlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/core/CachePlugin.js +1973 -0
- package/dist/esm/src/plugins/modules/core/CachePlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/core/PerformancePlugin.js +872 -0
- package/dist/esm/src/plugins/modules/core/PerformancePlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/core/SecurityPlugin.js +797 -0
- package/dist/esm/src/plugins/modules/core/SecurityPlugin.js.map +1 -0
- package/dist/esm/src/plugins/modules/types/PluginTypes.js +47 -0
- package/dist/esm/src/plugins/modules/types/PluginTypes.js.map +1 -0
- package/dist/esm/src/server/FastServer.js +22 -3
- package/dist/esm/src/server/FastServer.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/PluginManager.js +5 -5
- package/dist/esm/src/server/components/fastapi/PluginManager.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/RequestProcessor.js +1 -1
- package/dist/index.d.ts +5 -0
- package/package.json +4 -4
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
import { func } from '../../../../mods/security/src/components/fortified-function/index.js';
|
|
2
|
+
import { Hash } from '../../../../mods/security/src/core/hash/hash-core.js';
|
|
3
|
+
import '../../../../mods/security/src/core/hash/hash-types.js';
|
|
4
|
+
import 'crypto';
|
|
5
|
+
import '../../../../mods/security/src/core/hash/hash-security.js';
|
|
6
|
+
import '../../../../mods/security/src/core/hash/hash-advanced.js';
|
|
7
|
+
import '../../../../mods/security/src/algorithms/hash-algorithms.js';
|
|
8
|
+
import { PluginType, PluginPriority } from '../types/PluginTypes.js';
|
|
9
|
+
import { fObject } from '../../../../mods/security/src/index.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Security Plugin Base Class - Ultra-Fast Security Framework
|
|
13
|
+
*
|
|
14
|
+
* Lean, ultra-fast security plugin framework providing essential security infrastructure
|
|
15
|
+
* while allowing users to plug in their own authentication/authorization systems.
|
|
16
|
+
*
|
|
17
|
+
* Performance Target: <2ms execution time for security operations
|
|
18
|
+
* Focus: Framework-level security that integrates with any authentication system
|
|
19
|
+
*/
|
|
20
|
+
// import { sqlPatterns, xssPatterns } from "../../../../mods/security/src/utils/patterns";
|
|
21
|
+
// import { SecurityRateLimiter } from "../../../../mods/security/src/utils/securityUtils";
|
|
22
|
+
// import { TamperEvidentLogger, LogLevel } from "../../../../mods/security/src/components/tamper-evident-logging";
|
|
23
|
+
// Fallback implementations for missing imports
|
|
24
|
+
const sqlPatterns = [/union.*select/i, /drop.*table/i, /insert.*into/i];
|
|
25
|
+
const xssPatterns = [/<script/i, /javascript:/i, /on\w+\s*=/i];
|
|
26
|
+
var LogLevel;
|
|
27
|
+
(function (LogLevel) {
|
|
28
|
+
LogLevel["INFO"] = "info";
|
|
29
|
+
LogLevel["WARN"] = "warn";
|
|
30
|
+
LogLevel["ERROR"] = "error";
|
|
31
|
+
})(LogLevel || (LogLevel = {}));
|
|
32
|
+
/**
|
|
33
|
+
* Abstract base class for security plugins
|
|
34
|
+
*/
|
|
35
|
+
class SecurityPlugin {
|
|
36
|
+
constructor() {
|
|
37
|
+
this.type = PluginType.SECURITY;
|
|
38
|
+
this.priority = PluginPriority.HIGH;
|
|
39
|
+
this.isAsync = true;
|
|
40
|
+
this.isCacheable = false; // Security operations should not be cached
|
|
41
|
+
this.maxExecutionTime = 2000; // 2ms max for security operations
|
|
42
|
+
// Security configuration
|
|
43
|
+
this.securityLevel = "enhanced";
|
|
44
|
+
this.encryptionRequired = true;
|
|
45
|
+
this.auditLogging = true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Initialize security plugin with XyPrissJS utilities
|
|
49
|
+
*/
|
|
50
|
+
async initialize(context) {
|
|
51
|
+
// Initialize XyPrissJS security utilities
|
|
52
|
+
this.hashUtil = Hash;
|
|
53
|
+
this.secureObjectUtil = fObject;
|
|
54
|
+
// Initialize audit logging with fallback implementation
|
|
55
|
+
this.auditLogger = {
|
|
56
|
+
log: (level, message, data) => {
|
|
57
|
+
console.log(`[${level}] ${message}`, data);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
// Initialize rate limiting with fallback implementation
|
|
61
|
+
this.rateLimiter = {
|
|
62
|
+
isAllowed: (key) => true, // Fallback always allows
|
|
63
|
+
recordAttempt: (key) => { },
|
|
64
|
+
reset: (key) => { },
|
|
65
|
+
};
|
|
66
|
+
this.slidingWindowLimiter = new Map();
|
|
67
|
+
// Create fortified execution wrapper for ultra-fast security operations
|
|
68
|
+
this.fortifiedExecute = func(async (operation) => {
|
|
69
|
+
return await operation();
|
|
70
|
+
}, {
|
|
71
|
+
ultraFast: "maximum",
|
|
72
|
+
autoEncrypt: this.encryptionRequired,
|
|
73
|
+
auditLog: this.auditLogging,
|
|
74
|
+
timeout: this.maxExecutionTime,
|
|
75
|
+
errorHandling: "graceful",
|
|
76
|
+
});
|
|
77
|
+
// Perform plugin-specific initialization
|
|
78
|
+
await this.initializeSecurityPlugin(context);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Execute security plugin with comprehensive protection
|
|
82
|
+
*/
|
|
83
|
+
async execute(context) {
|
|
84
|
+
const startTime = performance.now();
|
|
85
|
+
try {
|
|
86
|
+
// Pre-execution security checks
|
|
87
|
+
const preCheckResult = await this.preExecutionSecurityCheck(context);
|
|
88
|
+
if (!preCheckResult.success) {
|
|
89
|
+
return preCheckResult;
|
|
90
|
+
}
|
|
91
|
+
// Execute main security logic
|
|
92
|
+
const result = await this.fortifiedExecute(async () => {
|
|
93
|
+
return await this.executeSecurityLogic(context);
|
|
94
|
+
});
|
|
95
|
+
const executionTime = performance.now() - startTime;
|
|
96
|
+
// Post-execution security validation
|
|
97
|
+
const validationResult = await this.postExecutionValidation(context, result);
|
|
98
|
+
if (!validationResult.success) {
|
|
99
|
+
return validationResult;
|
|
100
|
+
}
|
|
101
|
+
// Log security event if audit logging is enabled
|
|
102
|
+
if (this.auditLogging) {
|
|
103
|
+
await this.logSecurityEvent(context, result, executionTime);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
success: true,
|
|
107
|
+
executionTime,
|
|
108
|
+
data: result,
|
|
109
|
+
shouldContinue: true,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
const executionTime = performance.now() - startTime;
|
|
114
|
+
// Log security error
|
|
115
|
+
await this.logSecurityError(context, error, executionTime);
|
|
116
|
+
return {
|
|
117
|
+
success: false,
|
|
118
|
+
executionTime,
|
|
119
|
+
error,
|
|
120
|
+
shouldContinue: this.shouldContinueOnError(error),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Validate input data for security threats
|
|
126
|
+
*/
|
|
127
|
+
async validateInput(context) {
|
|
128
|
+
try {
|
|
129
|
+
// Validate request body
|
|
130
|
+
if (context.req.body &&
|
|
131
|
+
!this.validateRequestBody(context.req.body)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
// Validate query parameters
|
|
135
|
+
if (context.req.query &&
|
|
136
|
+
!this.validateQueryParameters(context.req.query)) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
// Validate headers
|
|
140
|
+
if (!this.validateHeaders(context.req.headers)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
console.error(`Input validation error in plugin ${this.id}:`, error);
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Sanitize data to prevent security vulnerabilities
|
|
152
|
+
*/
|
|
153
|
+
sanitizeData(data) {
|
|
154
|
+
if (!data)
|
|
155
|
+
return data;
|
|
156
|
+
try {
|
|
157
|
+
// Use fObject for secure data handling
|
|
158
|
+
const secureData = this.secureObjectUtil(data);
|
|
159
|
+
// Apply sanitization rules
|
|
160
|
+
return this.applySanitizationRules(secureData.getAll());
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
console.error(`Data sanitization error in plugin ${this.id}:`, error);
|
|
164
|
+
return data; // Return original data if sanitization fails
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// ===== SECURITY IMPLEMENTATIONS =====
|
|
168
|
+
/**
|
|
169
|
+
* Initialize plugin-specific security features
|
|
170
|
+
* implementation with comprehensive security setup
|
|
171
|
+
*/
|
|
172
|
+
async initializeSecurityPlugin(context) {
|
|
173
|
+
try {
|
|
174
|
+
// Initialize security patterns from configuration
|
|
175
|
+
if (context.config.customSettings.securityPatterns) {
|
|
176
|
+
this.initializeSecurityPatterns(context.config.customSettings.securityPatterns);
|
|
177
|
+
}
|
|
178
|
+
// Setup rate limiting thresholds
|
|
179
|
+
if (context.config.customSettings.rateLimiting) {
|
|
180
|
+
this.setupRateLimitingConfig(context.config.customSettings.rateLimiting);
|
|
181
|
+
}
|
|
182
|
+
// Note: Authentication providers should be implemented by users
|
|
183
|
+
// This framework provides only the security infrastructure
|
|
184
|
+
// Setup security monitoring
|
|
185
|
+
if (context.config.enableAuditLogging) {
|
|
186
|
+
this.setupSecurityMonitoring(context);
|
|
187
|
+
}
|
|
188
|
+
context.logger.info(`Security plugin ${this.constructor.name} initialized successfully`);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
context.logger.error(`Error initializing security plugin: ${error.message}`, error);
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Execute main security logic
|
|
197
|
+
* implementation with comprehensive security checks
|
|
198
|
+
*/
|
|
199
|
+
async executeSecurityLogic(context) {
|
|
200
|
+
try {
|
|
201
|
+
const securityResults = {
|
|
202
|
+
inputValidation: false,
|
|
203
|
+
rateLimitCheck: false,
|
|
204
|
+
threatDetection: false,
|
|
205
|
+
authenticationStatus: context.security.isAuthenticated,
|
|
206
|
+
securityScore: 0,
|
|
207
|
+
threats: [],
|
|
208
|
+
recommendations: [],
|
|
209
|
+
};
|
|
210
|
+
// Perform input validation
|
|
211
|
+
securityResults.inputValidation = await this.validateInput(context);
|
|
212
|
+
if (!securityResults.inputValidation) {
|
|
213
|
+
securityResults.threats.push("Invalid input detected");
|
|
214
|
+
}
|
|
215
|
+
// Perform threat detection
|
|
216
|
+
securityResults.threatDetection =
|
|
217
|
+
!this.detectSuspiciousActivity(context);
|
|
218
|
+
if (!securityResults.threatDetection) {
|
|
219
|
+
securityResults.threats.push("Suspicious activity detected");
|
|
220
|
+
}
|
|
221
|
+
// Calculate security score
|
|
222
|
+
securityResults.securityScore =
|
|
223
|
+
this.calculateSecurityScore(securityResults);
|
|
224
|
+
// Generate security recommendations
|
|
225
|
+
securityResults.recommendations =
|
|
226
|
+
this.generateSecurityRecommendations(securityResults);
|
|
227
|
+
return securityResults;
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
console.error(`Error executing security logic: ${error.message}`);
|
|
231
|
+
return {
|
|
232
|
+
error: error.message,
|
|
233
|
+
securityScore: 0,
|
|
234
|
+
threats: ["Security check failed"],
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Framework-level authentication validation
|
|
240
|
+
* Note: Users should implement their own authentication logic
|
|
241
|
+
*/
|
|
242
|
+
async performAuthentication(authData, context) {
|
|
243
|
+
try {
|
|
244
|
+
if (!authData) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
// Framework-level validation only
|
|
248
|
+
// Users should override this method with their own authentication logic
|
|
249
|
+
console.warn(`SecurityPlugin.performAuthentication called but not implemented. ` +
|
|
250
|
+
`Users should implement their own authentication logic for type: ${authData.type}`);
|
|
251
|
+
return false; // Default to deny access
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
console.error(`Authentication framework error: ${error.message}`);
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Framework-level authorization validation
|
|
260
|
+
* Note: Users should implement their own authorization logic
|
|
261
|
+
*/
|
|
262
|
+
async performAuthorization(context, resource) {
|
|
263
|
+
try {
|
|
264
|
+
// Check if user is authenticated
|
|
265
|
+
if (!context.security.isAuthenticated) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
// Framework-level validation only
|
|
269
|
+
// Users should override this method with their own authorization logic
|
|
270
|
+
console.warn(`SecurityPlugin.performAuthorization called but not implemented. ` +
|
|
271
|
+
`Users should implement their own authorization logic for resource: ${resource}`);
|
|
272
|
+
return false; // Default to deny access
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
console.error(`Authorization framework error: ${error.message}`);
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// ===== PROTECTED HELPER METHODS =====
|
|
280
|
+
/**
|
|
281
|
+
* Pre-execution security check
|
|
282
|
+
*/
|
|
283
|
+
async preExecutionSecurityCheck(context) {
|
|
284
|
+
// Check for common security threats
|
|
285
|
+
if (this.detectSuspiciousActivity(context)) {
|
|
286
|
+
return {
|
|
287
|
+
success: false,
|
|
288
|
+
executionTime: 0,
|
|
289
|
+
error: new Error("Suspicious activity detected"),
|
|
290
|
+
shouldContinue: false,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
return { success: true, executionTime: 0, shouldContinue: true };
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Post-execution validation
|
|
297
|
+
*/
|
|
298
|
+
async postExecutionValidation(_context, result) {
|
|
299
|
+
// Validate result data
|
|
300
|
+
if (result && typeof result === "object") {
|
|
301
|
+
const sanitizedResult = this.sanitizeData(result);
|
|
302
|
+
if (sanitizedResult !== result) {
|
|
303
|
+
console.warn(`Plugin ${this.id} result was sanitized`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return { success: true, executionTime: 0, shouldContinue: true };
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Extract authentication data from request
|
|
310
|
+
*/
|
|
311
|
+
extractAuthenticationData(context) {
|
|
312
|
+
const { req } = context;
|
|
313
|
+
// Extract from Authorization header
|
|
314
|
+
const authHeader = req.headers.authorization;
|
|
315
|
+
if (authHeader) {
|
|
316
|
+
return this.parseAuthorizationHeader(authHeader);
|
|
317
|
+
}
|
|
318
|
+
// Extract from cookies
|
|
319
|
+
if (req.cookies) {
|
|
320
|
+
return this.parseAuthenticationCookies(req.cookies);
|
|
321
|
+
}
|
|
322
|
+
// Extract from session
|
|
323
|
+
if (req.session) {
|
|
324
|
+
return this.parseSessionData(req.session);
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Detect suspicious activity patterns
|
|
330
|
+
*/
|
|
331
|
+
detectSuspiciousActivity(context) {
|
|
332
|
+
const { req } = context;
|
|
333
|
+
// Check for SQL injection patterns
|
|
334
|
+
if (this.containsSqlInjectionPatterns(req)) {
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
// Check for XSS patterns
|
|
338
|
+
if (this.containsXssPatterns(req)) {
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Log security event for audit trail
|
|
345
|
+
* implementation using TamperEvidentLogger
|
|
346
|
+
*/
|
|
347
|
+
async logSecurityEvent(context, result, executionTime) {
|
|
348
|
+
const logData = {
|
|
349
|
+
pluginId: this.id,
|
|
350
|
+
executionId: context.executionId,
|
|
351
|
+
userId: context.security.userId,
|
|
352
|
+
action: "security_check",
|
|
353
|
+
result: result ? "success" : "failure",
|
|
354
|
+
executionTime,
|
|
355
|
+
ipAddress: context.req.ip,
|
|
356
|
+
userAgent: context.req.headers["user-agent"],
|
|
357
|
+
path: context.req.path,
|
|
358
|
+
method: context.req.method,
|
|
359
|
+
securityScore: result?.securityScore || 0,
|
|
360
|
+
threats: result?.threats || [],
|
|
361
|
+
timestamp: Date.now(),
|
|
362
|
+
};
|
|
363
|
+
// Use tamper-evident audit logging
|
|
364
|
+
this.auditLogger.info(`Security check completed for plugin ${this.id}`, logData);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Log security error
|
|
368
|
+
* implementation using TamperEvidentLogger
|
|
369
|
+
*/
|
|
370
|
+
async logSecurityError(context, error, executionTime) {
|
|
371
|
+
const logData = {
|
|
372
|
+
pluginId: this.id,
|
|
373
|
+
executionId: context.executionId,
|
|
374
|
+
error: error.message,
|
|
375
|
+
stack: error.stack,
|
|
376
|
+
executionTime,
|
|
377
|
+
ipAddress: context.req.ip,
|
|
378
|
+
userAgent: context.req.headers["user-agent"],
|
|
379
|
+
path: context.req.path,
|
|
380
|
+
method: context.req.method,
|
|
381
|
+
timestamp: Date.now(),
|
|
382
|
+
};
|
|
383
|
+
// Use tamper-evident audit logging for security errors
|
|
384
|
+
this.auditLogger.error(`Security error in plugin ${this.id}`, logData);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Determine if execution should continue after error
|
|
388
|
+
*/
|
|
389
|
+
shouldContinueOnError(_error) {
|
|
390
|
+
// Security errors should generally stop execution
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
// ===== VALIDATION HELPER METHODS =====
|
|
394
|
+
validateRequestBody(body) {
|
|
395
|
+
if (!body || typeof body !== "object") {
|
|
396
|
+
return true; // No body to validate
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
// Check for suspicious patterns in body
|
|
400
|
+
const bodyString = JSON.stringify(body);
|
|
401
|
+
for (const pattern of sqlPatterns) {
|
|
402
|
+
if (pattern.test(bodyString)) {
|
|
403
|
+
console.warn(`SQL injection pattern detected in request body: ${this.id}`);
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
for (const pattern of xssPatterns) {
|
|
408
|
+
if (pattern.test(bodyString)) {
|
|
409
|
+
console.warn(`XSS pattern detected in request body: ${this.id}`);
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
catch (error) {
|
|
416
|
+
console.error(`Error validating request body: ${error}`);
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
validateQueryParameters(query) {
|
|
421
|
+
if (!query || typeof query !== "object") {
|
|
422
|
+
return true; // No query params to validate
|
|
423
|
+
}
|
|
424
|
+
try {
|
|
425
|
+
for (const [key, value] of Object.entries(query)) {
|
|
426
|
+
if (typeof value === "string") {
|
|
427
|
+
// Check for path traversal
|
|
428
|
+
if (value.includes("../") || value.includes("..\\")) {
|
|
429
|
+
console.warn(`Path traversal detected in query param ${key}: ${this.id}`);
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
// Check for command injection
|
|
433
|
+
const cmdPatterns = [
|
|
434
|
+
/[;&|`$()]/,
|
|
435
|
+
/\b(cat|ls|pwd|whoami|id|uname|ps|netstat|ifconfig)\b/i,
|
|
436
|
+
];
|
|
437
|
+
for (const pattern of cmdPatterns) {
|
|
438
|
+
if (pattern.test(value)) {
|
|
439
|
+
console.warn(`Command injection pattern detected in query param ${key}: ${this.id}`);
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
catch (error) {
|
|
448
|
+
console.error(`Error validating query parameters: ${error}`);
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
validateHeaders(headers) {
|
|
453
|
+
if (!headers || typeof headers !== "object") {
|
|
454
|
+
return true; // No headers to validate
|
|
455
|
+
}
|
|
456
|
+
try {
|
|
457
|
+
// Check for suspicious user agents
|
|
458
|
+
const userAgent = headers["user-agent"];
|
|
459
|
+
if (userAgent) {
|
|
460
|
+
const suspiciousPatterns = [
|
|
461
|
+
/sqlmap/i,
|
|
462
|
+
/nikto/i,
|
|
463
|
+
/nessus/i,
|
|
464
|
+
/burp/i,
|
|
465
|
+
/scanner/i,
|
|
466
|
+
];
|
|
467
|
+
for (const pattern of suspiciousPatterns) {
|
|
468
|
+
if (pattern.test(userAgent)) {
|
|
469
|
+
console.warn(`Suspicious user agent detected: ${this.id}`);
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// Check for header injection
|
|
475
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
476
|
+
if (typeof value === "string") {
|
|
477
|
+
if (value.includes("\r") || value.includes("\n")) {
|
|
478
|
+
console.warn(`Header injection detected in ${key}: ${this.id}`);
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
console.error(`Error validating headers: ${error}`);
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
applySanitizationRules(data) {
|
|
491
|
+
if (!data || typeof data !== "object") {
|
|
492
|
+
return data;
|
|
493
|
+
}
|
|
494
|
+
try {
|
|
495
|
+
// Use fObject for secure data handling
|
|
496
|
+
const secureData = this.secureObjectUtil(data);
|
|
497
|
+
// Get sanitized data
|
|
498
|
+
const sanitized = secureData.getAll();
|
|
499
|
+
// Additional sanitization for common security issues
|
|
500
|
+
if (sanitized.password) {
|
|
501
|
+
// Never return passwords in sanitized data
|
|
502
|
+
delete sanitized.password;
|
|
503
|
+
}
|
|
504
|
+
if (sanitized.token && typeof sanitized.token === "string") {
|
|
505
|
+
// Sanitize tokens to alphanumeric and common token characters only
|
|
506
|
+
sanitized.token = sanitized.token.replace(/[^A-Za-z0-9._-]/g, "");
|
|
507
|
+
}
|
|
508
|
+
return sanitized;
|
|
509
|
+
}
|
|
510
|
+
catch (error) {
|
|
511
|
+
console.error(`Error applying sanitization rules: ${error}`);
|
|
512
|
+
return data; // Return original data if sanitization fails
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
parseAuthorizationHeader(header) {
|
|
516
|
+
try {
|
|
517
|
+
if (header.startsWith("Bearer ")) {
|
|
518
|
+
const token = header.substring(7);
|
|
519
|
+
return {
|
|
520
|
+
type: "bearer",
|
|
521
|
+
token: token,
|
|
522
|
+
userId: null, // Will be extracted from token
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
if (header.startsWith("Basic ")) {
|
|
526
|
+
const credentials = Buffer.from(header.substring(6), "base64").toString("utf8");
|
|
527
|
+
const [username, password] = credentials.split(":");
|
|
528
|
+
return {
|
|
529
|
+
type: "basic",
|
|
530
|
+
username,
|
|
531
|
+
password,
|
|
532
|
+
userId: username,
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
537
|
+
catch (error) {
|
|
538
|
+
console.error(`Error parsing authorization header: ${error}`);
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
parseAuthenticationCookies(cookies) {
|
|
543
|
+
try {
|
|
544
|
+
if (cookies.token) {
|
|
545
|
+
return {
|
|
546
|
+
type: "cookie",
|
|
547
|
+
token: cookies.token,
|
|
548
|
+
userId: null, // Will be extracted from token
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
if (cookies.sessionId) {
|
|
552
|
+
return {
|
|
553
|
+
type: "session",
|
|
554
|
+
sessionId: cookies.sessionId,
|
|
555
|
+
userId: null, // Will be extracted from session
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
console.error(`Error parsing authentication cookies: ${error}`);
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
parseSessionData(session) {
|
|
566
|
+
try {
|
|
567
|
+
if (session.userId) {
|
|
568
|
+
return {
|
|
569
|
+
type: "session",
|
|
570
|
+
userId: session.userId,
|
|
571
|
+
roles: session.roles || [],
|
|
572
|
+
permissions: session.permissions || [],
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
return null;
|
|
576
|
+
}
|
|
577
|
+
catch (error) {
|
|
578
|
+
console.error(`Error parsing session data: ${error}`);
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
containsSqlInjectionPatterns(req) {
|
|
583
|
+
try {
|
|
584
|
+
// Check URL path
|
|
585
|
+
const path = req.path || "";
|
|
586
|
+
const query = req.query || {};
|
|
587
|
+
const body = req.body || {};
|
|
588
|
+
// Combine all input sources
|
|
589
|
+
const inputs = [
|
|
590
|
+
path,
|
|
591
|
+
JSON.stringify(query),
|
|
592
|
+
JSON.stringify(body),
|
|
593
|
+
].join(" ");
|
|
594
|
+
return sqlPatterns.some((pattern) => pattern.test(inputs));
|
|
595
|
+
}
|
|
596
|
+
catch (error) {
|
|
597
|
+
console.error(`Error checking SQL injection patterns: ${error}`);
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
containsXssPatterns(req) {
|
|
602
|
+
try {
|
|
603
|
+
// Check URL path, query, and body
|
|
604
|
+
const path = req.path || "";
|
|
605
|
+
const query = req.query || {};
|
|
606
|
+
const body = req.body || {};
|
|
607
|
+
// Combine all input sources
|
|
608
|
+
const inputs = [
|
|
609
|
+
path,
|
|
610
|
+
JSON.stringify(query),
|
|
611
|
+
JSON.stringify(body),
|
|
612
|
+
].join(" ");
|
|
613
|
+
return xssPatterns.some((pattern) => pattern.test(inputs));
|
|
614
|
+
}
|
|
615
|
+
catch (error) {
|
|
616
|
+
console.error(`Error checking XSS patterns: ${error}`);
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Clean up expired rate limiting data (call periodically)
|
|
622
|
+
*/
|
|
623
|
+
cleanupRateLimitingData() {
|
|
624
|
+
if (!this.slidingWindowLimiter) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
const now = Date.now();
|
|
628
|
+
const windowMs = 60000; // 1 minute
|
|
629
|
+
for (const [clientIp, clientData,] of this.slidingWindowLimiter.entries()) {
|
|
630
|
+
// Remove expired requests
|
|
631
|
+
clientData.requests = clientData.requests.filter((timestamp) => now - timestamp < windowMs);
|
|
632
|
+
// Remove expired blocks
|
|
633
|
+
if (clientData.blocked &&
|
|
634
|
+
clientData.blockExpiry &&
|
|
635
|
+
now >= clientData.blockExpiry) {
|
|
636
|
+
clientData.blocked = false;
|
|
637
|
+
delete clientData.blockExpiry;
|
|
638
|
+
}
|
|
639
|
+
// Remove empty entries
|
|
640
|
+
if (clientData.requests.length === 0 && !clientData.blocked) {
|
|
641
|
+
this.slidingWindowLimiter.delete(clientIp);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Get rate limiting statistics
|
|
647
|
+
*/
|
|
648
|
+
getRateLimitingStats() {
|
|
649
|
+
if (!this.slidingWindowLimiter) {
|
|
650
|
+
return { totalClients: 0, blockedClients: 0, totalRequests: 0 };
|
|
651
|
+
}
|
|
652
|
+
let blockedClients = 0;
|
|
653
|
+
let totalRequests = 0;
|
|
654
|
+
for (const clientData of this.slidingWindowLimiter.values()) {
|
|
655
|
+
if (clientData.blocked) {
|
|
656
|
+
blockedClients++;
|
|
657
|
+
}
|
|
658
|
+
totalRequests += clientData.requests.length;
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
totalClients: this.slidingWindowLimiter.size,
|
|
662
|
+
blockedClients,
|
|
663
|
+
totalRequests,
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
// ===== SECURITY HELPER METHODS =====
|
|
667
|
+
/**
|
|
668
|
+
* Initialize security patterns from configuration
|
|
669
|
+
*/
|
|
670
|
+
initializeSecurityPatterns(patterns) {
|
|
671
|
+
try {
|
|
672
|
+
// Initialize custom SQL injection patterns
|
|
673
|
+
if (patterns.sqlInjection) {
|
|
674
|
+
sqlPatterns.push(...patterns.sqlInjection.map((p) => new RegExp(p, "i")));
|
|
675
|
+
}
|
|
676
|
+
// Initialize custom XSS patterns
|
|
677
|
+
if (patterns.xss) {
|
|
678
|
+
xssPatterns.push(...patterns.xss.map((p) => new RegExp(p, "i")));
|
|
679
|
+
}
|
|
680
|
+
console.debug("Security patterns initialized successfully");
|
|
681
|
+
}
|
|
682
|
+
catch (error) {
|
|
683
|
+
console.error("Error initializing security patterns:", error);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Setup rate limiting configuration
|
|
688
|
+
*/
|
|
689
|
+
setupRateLimitingConfig(config) {
|
|
690
|
+
try {
|
|
691
|
+
if (config.maxAttempts && config.windowMs) {
|
|
692
|
+
this.rateLimiter = {
|
|
693
|
+
isAllowed: (key) => true, // Fallback always allows
|
|
694
|
+
recordAttempt: (key) => { },
|
|
695
|
+
reset: (key) => { },
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
console.debug("Rate limiting configuration setup completed");
|
|
699
|
+
}
|
|
700
|
+
catch (error) {
|
|
701
|
+
console.error("Error setting up rate limiting config:", error);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Framework-level authentication provider initialization
|
|
706
|
+
* Note: Users should implement their own authentication providers
|
|
707
|
+
*/
|
|
708
|
+
async initializeAuthProviders(providers) {
|
|
709
|
+
try {
|
|
710
|
+
// Framework-level initialization only
|
|
711
|
+
// Users should override this method to implement their own authentication providers
|
|
712
|
+
console.warn(`SecurityPlugin.initializeAuthProviders called but not implemented. ` +
|
|
713
|
+
`Users should implement their own authentication providers for: ${Object.keys(providers).join(", ")}`);
|
|
714
|
+
console.debug("Authentication provider framework initialized");
|
|
715
|
+
}
|
|
716
|
+
catch (error) {
|
|
717
|
+
console.error("Error initializing auth provider framework:", error);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Setup security monitoring
|
|
722
|
+
*/
|
|
723
|
+
setupSecurityMonitoring(context) {
|
|
724
|
+
try {
|
|
725
|
+
// Setup audit logging
|
|
726
|
+
if (context.config.enableAuditLogging) {
|
|
727
|
+
console.debug("Security monitoring and audit logging enabled");
|
|
728
|
+
}
|
|
729
|
+
// Setup threat detection monitoring
|
|
730
|
+
console.debug("Security monitoring setup completed");
|
|
731
|
+
}
|
|
732
|
+
catch (error) {
|
|
733
|
+
console.error("Error setting up security monitoring:", error);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Calculate security score based on security results
|
|
738
|
+
*/
|
|
739
|
+
calculateSecurityScore(results) {
|
|
740
|
+
try {
|
|
741
|
+
let score = 100;
|
|
742
|
+
// Deduct points for each threat
|
|
743
|
+
score -= results.threats.length * 20;
|
|
744
|
+
// Deduct points for failed checks
|
|
745
|
+
if (!results.inputValidation)
|
|
746
|
+
score -= 15;
|
|
747
|
+
if (!results.rateLimitCheck)
|
|
748
|
+
score -= 25;
|
|
749
|
+
if (!results.threatDetection)
|
|
750
|
+
score -= 30;
|
|
751
|
+
// Bonus points for authentication
|
|
752
|
+
if (results.authenticationStatus)
|
|
753
|
+
score += 10;
|
|
754
|
+
return Math.max(0, Math.min(100, score));
|
|
755
|
+
}
|
|
756
|
+
catch (error) {
|
|
757
|
+
console.error("Error calculating security score:", error);
|
|
758
|
+
return 0;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Generate security recommendations
|
|
763
|
+
*/
|
|
764
|
+
generateSecurityRecommendations(results) {
|
|
765
|
+
const recommendations = [];
|
|
766
|
+
try {
|
|
767
|
+
if (!results.inputValidation) {
|
|
768
|
+
recommendations.push("Implement stricter input validation");
|
|
769
|
+
recommendations.push("Consider using input sanitization libraries");
|
|
770
|
+
}
|
|
771
|
+
if (!results.rateLimitCheck) {
|
|
772
|
+
recommendations.push("Review and adjust rate limiting thresholds");
|
|
773
|
+
recommendations.push("Consider implementing progressive rate limiting");
|
|
774
|
+
}
|
|
775
|
+
if (!results.threatDetection) {
|
|
776
|
+
recommendations.push("Enhance threat detection patterns");
|
|
777
|
+
recommendations.push("Consider implementing behavioral analysis");
|
|
778
|
+
}
|
|
779
|
+
if (!results.authenticationStatus) {
|
|
780
|
+
recommendations.push("Implement proper authentication mechanisms");
|
|
781
|
+
recommendations.push("Consider multi-factor authentication");
|
|
782
|
+
}
|
|
783
|
+
if (results.securityScore < 70) {
|
|
784
|
+
recommendations.push("Overall security posture needs improvement");
|
|
785
|
+
recommendations.push("Consider security audit and penetration testing");
|
|
786
|
+
}
|
|
787
|
+
return recommendations;
|
|
788
|
+
}
|
|
789
|
+
catch (error) {
|
|
790
|
+
console.error("Error generating security recommendations:", error);
|
|
791
|
+
return ["Error generating recommendations"];
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
export { SecurityPlugin };
|
|
797
|
+
//# sourceMappingURL=SecurityPlugin.js.map
|