xypriss 2.3.7 → 3.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 +21 -19
- package/dist/cjs/mods/security/src/index.js +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/middleware/built-in/BuiltInMiddleware.js +123 -14
- package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
- package/dist/cjs/src/middleware/built-in/security/BrowserOnlyProtector.js +552 -0
- package/dist/cjs/src/middleware/built-in/security/BrowserOnlyProtector.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/security/RequestSignatureProtector.js +465 -0
- package/dist/cjs/src/middleware/built-in/security/RequestSignatureProtector.js.map +1 -0
- package/dist/cjs/src/middleware/built-in/security/TerminalOnlyProtector.js +477 -0
- package/dist/cjs/src/middleware/built-in/security/TerminalOnlyProtector.js.map +1 -0
- package/dist/cjs/src/middleware/security-middleware.js +257 -91
- package/dist/cjs/src/middleware/security-middleware.js.map +1 -1
- package/dist/cjs/src/server/components/fastapi/templates/redirectTemp.js +1 -1
- package/dist/cjs/src/server/const/default.js +1 -1
- package/dist/cjs/src/server/const/default.js.map +1 -1
- package/dist/esm/mods/security/src/index.js +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/middleware/built-in/BuiltInMiddleware.js +123 -14
- package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
- package/dist/esm/src/middleware/built-in/security/BrowserOnlyProtector.js +550 -0
- package/dist/esm/src/middleware/built-in/security/BrowserOnlyProtector.js.map +1 -0
- package/dist/esm/src/middleware/built-in/security/RequestSignatureProtector.js +444 -0
- package/dist/esm/src/middleware/built-in/security/RequestSignatureProtector.js.map +1 -0
- package/dist/esm/src/middleware/built-in/security/TerminalOnlyProtector.js +475 -0
- package/dist/esm/src/middleware/built-in/security/TerminalOnlyProtector.js.map +1 -0
- package/dist/esm/src/middleware/security-middleware.js +257 -91
- package/dist/esm/src/middleware/security-middleware.js.map +1 -1
- package/dist/esm/src/server/components/fastapi/templates/redirectTemp.js +1 -1
- package/dist/esm/src/server/const/default.js +1 -1
- package/dist/esm/src/server/const/default.js.map +1 -1
- package/dist/index.d.ts +268 -10
- package/package.json +6 -5
- package/scripts/install-memory-cli.js +1 -1
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import { Logger } from '../../../../shared/logger/Logger.js';
|
|
2
|
+
import * as crypto from 'crypto';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* XyRS - XyPriss Request Signature Protector
|
|
6
|
+
* Validates request signatures for API authentication
|
|
7
|
+
* Uses a predefined header name with developer-configured secret value
|
|
8
|
+
* Enhanced with robust validation and security measures
|
|
9
|
+
*/
|
|
10
|
+
class RequestSignatureProtector {
|
|
11
|
+
constructor(options, logger) {
|
|
12
|
+
this.HEADER_NAME = "XP-Request-Sig";
|
|
13
|
+
this.failedAttempts = new Map();
|
|
14
|
+
this.CLEANUP_INTERVAL = 60000; // 1 minute
|
|
15
|
+
// Strict validation of required secret
|
|
16
|
+
this.validateSecret(options.secret, options.minSecretLength);
|
|
17
|
+
this.config = {
|
|
18
|
+
errorMessage: "Invalid or missing request signature",
|
|
19
|
+
statusCode: 401,
|
|
20
|
+
debug: false,
|
|
21
|
+
caseSensitive: true,
|
|
22
|
+
trimValue: true,
|
|
23
|
+
maxHeaderLength: 512,
|
|
24
|
+
maxFailedAttempts: 5,
|
|
25
|
+
blockDuration: 15 * 60 * 1000, // 15 minutes
|
|
26
|
+
minSecretLength: 32,
|
|
27
|
+
timingSafeComparison: true,
|
|
28
|
+
rejectSuspiciousPatterns: true,
|
|
29
|
+
...options,
|
|
30
|
+
};
|
|
31
|
+
// Store hashed version of secret for additional security
|
|
32
|
+
this.SECRET_HASH = this.hashSecret(this.config.secret);
|
|
33
|
+
// Initialize logger
|
|
34
|
+
this.logger =
|
|
35
|
+
logger ||
|
|
36
|
+
new Logger({
|
|
37
|
+
enabled: true,
|
|
38
|
+
level: "debug",
|
|
39
|
+
components: { security: true },
|
|
40
|
+
types: { debug: true },
|
|
41
|
+
});
|
|
42
|
+
// Start cleanup timer for failed attempts tracking
|
|
43
|
+
this.startCleanupTimer();
|
|
44
|
+
this.logSecurityEvent("info", "XyRS initialized with strict validation");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get the request signature middleware function
|
|
48
|
+
*/
|
|
49
|
+
getMiddleware() {
|
|
50
|
+
return (req, res, next) => {
|
|
51
|
+
this.handleRequest(req, res, next);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Handle incoming request and validate signature
|
|
56
|
+
*/
|
|
57
|
+
handleRequest(req, res, next) {
|
|
58
|
+
const clientId = this.extractClientIdentifier(req);
|
|
59
|
+
// Check if client is currently blocked
|
|
60
|
+
if (this.isClientBlocked(clientId)) {
|
|
61
|
+
return this.blockRequest(res, "RATE_LIMITED", "Too many failed authentication attempts. Temporarily blocked.", clientId);
|
|
62
|
+
}
|
|
63
|
+
if (this.config.debug) {
|
|
64
|
+
this.logger.debug("security", "XyRS validating request signature");
|
|
65
|
+
}
|
|
66
|
+
// Strict header extraction
|
|
67
|
+
const signature = this.extractSignatureHeader(req);
|
|
68
|
+
if (signature === null) {
|
|
69
|
+
this.recordFailedAttempt(clientId);
|
|
70
|
+
return this.blockRequest(res, "MISSING_SIGNATURE", `Required header '${this.HEADER_NAME}' is missing or malformed`, clientId);
|
|
71
|
+
}
|
|
72
|
+
// Length validation to prevent DoS
|
|
73
|
+
if (!this.validateHeaderLength(signature)) {
|
|
74
|
+
this.recordFailedAttempt(clientId);
|
|
75
|
+
return this.blockRequest(res, "INVALID_HEADER_LENGTH", `Header value exceeds maximum allowed length`, clientId);
|
|
76
|
+
}
|
|
77
|
+
// Suspicious pattern detection
|
|
78
|
+
if (this.config.rejectSuspiciousPatterns &&
|
|
79
|
+
this.containsSuspiciousPatterns(signature)) {
|
|
80
|
+
this.recordFailedAttempt(clientId);
|
|
81
|
+
return this.blockRequest(res, "SUSPICIOUS_PATTERN", `Header contains suspicious or malicious patterns`, clientId);
|
|
82
|
+
}
|
|
83
|
+
// Process signature value
|
|
84
|
+
const processedSignature = this.processSignatureValue(signature);
|
|
85
|
+
const expectedSignature = this.processSignatureValue(this.config.secret);
|
|
86
|
+
// Validate signature with timing-safe comparison
|
|
87
|
+
const isValid = this.compareSignatures(processedSignature, expectedSignature);
|
|
88
|
+
if (!isValid) {
|
|
89
|
+
this.recordFailedAttempt(clientId);
|
|
90
|
+
this.logSecurityEvent("warning", "Invalid signature attempt", {
|
|
91
|
+
clientId,
|
|
92
|
+
signatureLength: signature.length,
|
|
93
|
+
});
|
|
94
|
+
return this.blockRequest(res, "INVALID_SIGNATURE", `Header '${this.HEADER_NAME}' value does not match expected signature`, clientId);
|
|
95
|
+
}
|
|
96
|
+
// Signature is valid - clear any failed attempts
|
|
97
|
+
this.clearFailedAttempts(clientId);
|
|
98
|
+
if (this.config.debug) {
|
|
99
|
+
this.logger.debug("security", "XyRS signature validation passed");
|
|
100
|
+
}
|
|
101
|
+
next();
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Extract client identifier for rate limiting (IP-based)
|
|
105
|
+
*/
|
|
106
|
+
extractClientIdentifier(req) {
|
|
107
|
+
// Try multiple methods to get real IP
|
|
108
|
+
const ip = req.ip ||
|
|
109
|
+
req.headers["x-forwarded-for"]?.split(",")[0]?.trim() ||
|
|
110
|
+
req.headers["x-real-ip"] ||
|
|
111
|
+
req.connection?.remoteAddress ||
|
|
112
|
+
req.socket?.remoteAddress ||
|
|
113
|
+
"unknown";
|
|
114
|
+
return this.sanitizeClientId(ip);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Sanitize client identifier
|
|
118
|
+
*/
|
|
119
|
+
sanitizeClientId(clientId) {
|
|
120
|
+
// Remove IPv6 prefix if present
|
|
121
|
+
let sanitized = clientId.replace(/^::ffff:/, "");
|
|
122
|
+
// Keep only alphanumeric, dots, colons, and hyphens
|
|
123
|
+
sanitized = sanitized.replace(/[^a-zA-Z0-9.:_-]/g, "");
|
|
124
|
+
return sanitized || "unknown";
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Strictly extract signature header with no fallbacks
|
|
128
|
+
*/
|
|
129
|
+
extractSignatureHeader(req) {
|
|
130
|
+
if (!req.headers || typeof req.headers !== "object") {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
// Only check lowercase version (standard HTTP header convention)
|
|
134
|
+
const headerKey = this.HEADER_NAME.toLowerCase();
|
|
135
|
+
const signature = req.headers[headerKey];
|
|
136
|
+
// Strict type checking
|
|
137
|
+
if (typeof signature !== "string") {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
// Reject empty or whitespace-only headers
|
|
141
|
+
if (signature.length === 0 || /^\s*$/.test(signature)) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return signature;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Validate header length to prevent DoS attacks
|
|
148
|
+
*/
|
|
149
|
+
validateHeaderLength(signature) {
|
|
150
|
+
return (signature.length > 0 &&
|
|
151
|
+
signature.length <= (this.config.maxHeaderLength || 512));
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Detect suspicious patterns in header value
|
|
155
|
+
*/
|
|
156
|
+
containsSuspiciousPatterns(signature) {
|
|
157
|
+
// Check for common attack patterns
|
|
158
|
+
const suspiciousPatterns = [
|
|
159
|
+
/[<>\"'`]/g, // HTML/Script injection characters
|
|
160
|
+
/\.\./g, // Path traversal
|
|
161
|
+
/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, // Control characters
|
|
162
|
+
/\${.*}/g, // Template injection
|
|
163
|
+
/\|\||&&/g, // Command injection
|
|
164
|
+
/(\r\n|\n|\r)/g, // CRLF injection
|
|
165
|
+
];
|
|
166
|
+
return suspiciousPatterns.some((pattern) => pattern.test(signature));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Process signature value based on configuration
|
|
170
|
+
*/
|
|
171
|
+
processSignatureValue(value) {
|
|
172
|
+
return this.config.trimValue ? value.trim() : value;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Compare signatures with optional timing-safe comparison
|
|
176
|
+
*/
|
|
177
|
+
compareSignatures(received, expected) {
|
|
178
|
+
// Always check lengths first (fast rejection)
|
|
179
|
+
if (received.length !== expected.length) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
if (this.config.timingSafeComparison) {
|
|
183
|
+
return this.timingSafeEqual(received, expected);
|
|
184
|
+
}
|
|
185
|
+
// Standard comparison
|
|
186
|
+
return this.config.caseSensitive
|
|
187
|
+
? received === expected
|
|
188
|
+
: received.toLowerCase() === expected.toLowerCase();
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Timing-safe string comparison to prevent timing attacks
|
|
192
|
+
*/
|
|
193
|
+
timingSafeEqual(a, b) {
|
|
194
|
+
// Convert to buffers for timing-safe comparison
|
|
195
|
+
const bufA = Buffer.from(this.config.caseSensitive ? a : a.toLowerCase());
|
|
196
|
+
const bufB = Buffer.from(this.config.caseSensitive ? b : b.toLowerCase());
|
|
197
|
+
if (bufA.length !== bufB.length) {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
return crypto.timingSafeEqual(bufA, bufB);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Check if client is currently blocked due to failed attempts
|
|
209
|
+
*/
|
|
210
|
+
isClientBlocked(clientId) {
|
|
211
|
+
const attempt = this.failedAttempts.get(clientId);
|
|
212
|
+
if (!attempt || !attempt.blockedUntil) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
const now = Date.now();
|
|
216
|
+
if (now >= attempt.blockedUntil) {
|
|
217
|
+
// Block period expired
|
|
218
|
+
this.failedAttempts.delete(clientId);
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Record failed authentication attempt
|
|
225
|
+
*/
|
|
226
|
+
recordFailedAttempt(clientId) {
|
|
227
|
+
const now = Date.now();
|
|
228
|
+
const attempt = this.failedAttempts.get(clientId) || {
|
|
229
|
+
count: 0,
|
|
230
|
+
blockedUntil: null,
|
|
231
|
+
lastAttempt: now,
|
|
232
|
+
};
|
|
233
|
+
attempt.count += 1;
|
|
234
|
+
attempt.lastAttempt = now;
|
|
235
|
+
// Block if threshold exceeded
|
|
236
|
+
if (attempt.count >= (this.config.maxFailedAttempts || 5)) {
|
|
237
|
+
attempt.blockedUntil = now + (this.config.blockDuration || 900000);
|
|
238
|
+
this.logSecurityEvent("warning", "Client blocked due to failed attempts", {
|
|
239
|
+
clientId,
|
|
240
|
+
attempts: attempt.count,
|
|
241
|
+
blockedUntil: new Date(attempt.blockedUntil).toISOString(),
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
this.failedAttempts.set(clientId, attempt);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Clear failed attempts for a client
|
|
248
|
+
*/
|
|
249
|
+
clearFailedAttempts(clientId) {
|
|
250
|
+
this.failedAttempts.delete(clientId);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Validate secret meets security requirements
|
|
254
|
+
*/
|
|
255
|
+
validateSecret(secret, minLength) {
|
|
256
|
+
const minLen = minLength || 32;
|
|
257
|
+
if (!secret || typeof secret !== "string") {
|
|
258
|
+
throw new Error("RequestSignatureProtector: secret is required and must be a string");
|
|
259
|
+
}
|
|
260
|
+
const trimmedSecret = secret.trim();
|
|
261
|
+
if (trimmedSecret.length === 0) {
|
|
262
|
+
throw new Error("RequestSignatureProtector: secret cannot be empty or whitespace-only");
|
|
263
|
+
}
|
|
264
|
+
if (trimmedSecret.length < minLen) {
|
|
265
|
+
throw new Error(`RequestSignatureProtector: secret must be at least ${minLen} characters long (current: ${trimmedSecret.length})`);
|
|
266
|
+
}
|
|
267
|
+
// Check for weak secrets
|
|
268
|
+
if (this.isWeakSecret(trimmedSecret)) {
|
|
269
|
+
throw new Error("RequestSignatureProtector: secret appears to be weak. Use a cryptographically strong random value.");
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Detect weak/predictable secrets
|
|
274
|
+
*/
|
|
275
|
+
isWeakSecret(secret) {
|
|
276
|
+
const weakPatterns = [
|
|
277
|
+
/^[0-9]+$/, // Only numbers
|
|
278
|
+
/^[a-zA-Z]+$/, // Only letters
|
|
279
|
+
/^(.)\1+$/, // Repeated character
|
|
280
|
+
/^(123|abc|password|secret|key|test|demo|admin)/i, // Common words
|
|
281
|
+
/^[a-f0-9]{32}$/i, // Looks like MD5 (weak)
|
|
282
|
+
];
|
|
283
|
+
return weakPatterns.some((pattern) => pattern.test(secret));
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Hash secret for internal verification
|
|
287
|
+
*/
|
|
288
|
+
hashSecret(secret) {
|
|
289
|
+
return crypto.createHash("sha256").update(secret).digest("hex");
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Start cleanup timer for failed attempts
|
|
293
|
+
*/
|
|
294
|
+
startCleanupTimer() {
|
|
295
|
+
this.cleanupTimer = setInterval(() => {
|
|
296
|
+
this.cleanupExpiredAttempts();
|
|
297
|
+
}, this.CLEANUP_INTERVAL);
|
|
298
|
+
// Don't keep process alive for cleanup
|
|
299
|
+
if (this.cleanupTimer.unref) {
|
|
300
|
+
this.cleanupTimer.unref();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Clean up expired failed attempt records
|
|
305
|
+
*/
|
|
306
|
+
cleanupExpiredAttempts() {
|
|
307
|
+
const now = Date.now();
|
|
308
|
+
const expiredClients = [];
|
|
309
|
+
for (const [clientId, attempt] of this.failedAttempts.entries()) {
|
|
310
|
+
// Remove if block expired and no recent attempts
|
|
311
|
+
if (attempt.blockedUntil &&
|
|
312
|
+
now >= attempt.blockedUntil &&
|
|
313
|
+
now - attempt.lastAttempt > this.CLEANUP_INTERVAL) {
|
|
314
|
+
expiredClients.push(clientId);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
expiredClients.forEach((clientId) => this.failedAttempts.delete(clientId));
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Block the request with appropriate error response
|
|
321
|
+
*/
|
|
322
|
+
blockRequest(res, code, details, clientId) {
|
|
323
|
+
const isDevelopment = this.config.debug;
|
|
324
|
+
const response = {
|
|
325
|
+
error: isDevelopment
|
|
326
|
+
? this.config.errorMessage
|
|
327
|
+
: "Authentication required",
|
|
328
|
+
timestamp: new Date().toISOString(),
|
|
329
|
+
code: "NEHONIX_XYRS_001",
|
|
330
|
+
};
|
|
331
|
+
// Add detailed info only in debug mode
|
|
332
|
+
if (isDevelopment) {
|
|
333
|
+
response.xyrs = {
|
|
334
|
+
module: "RequestSignature",
|
|
335
|
+
code,
|
|
336
|
+
details,
|
|
337
|
+
requiredHeader: this.HEADER_NAME,
|
|
338
|
+
hint: "Include the X-XyRS header with your configured secret value",
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
if (this.config.debug && clientId) {
|
|
342
|
+
this.logger.debug("security", "XyRS blocking request", {
|
|
343
|
+
code,
|
|
344
|
+
details,
|
|
345
|
+
clientId,
|
|
346
|
+
requiredHeader: this.HEADER_NAME,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
res.status(this.config.statusCode).json(response);
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Log security events
|
|
353
|
+
*/
|
|
354
|
+
logSecurityEvent(level, message, metadata) {
|
|
355
|
+
if (this.config.debug) {
|
|
356
|
+
const logMethod = level === "error"
|
|
357
|
+
? "error"
|
|
358
|
+
: level === "warning"
|
|
359
|
+
? "warn"
|
|
360
|
+
: "debug";
|
|
361
|
+
this.logger[logMethod]("security", message, metadata);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Update configuration with strict validation
|
|
366
|
+
*/
|
|
367
|
+
updateConfig(newConfig) {
|
|
368
|
+
if (newConfig.secret !== undefined) {
|
|
369
|
+
this.validateSecret(newConfig.secret, newConfig.minSecretLength);
|
|
370
|
+
}
|
|
371
|
+
this.config = { ...this.config, ...newConfig };
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Get current configuration (without exposing the secret)
|
|
375
|
+
*/
|
|
376
|
+
getConfig() {
|
|
377
|
+
return {
|
|
378
|
+
errorMessage: this.config.errorMessage,
|
|
379
|
+
statusCode: this.config.statusCode,
|
|
380
|
+
debug: this.config.debug,
|
|
381
|
+
caseSensitive: this.config.caseSensitive,
|
|
382
|
+
trimValue: this.config.trimValue,
|
|
383
|
+
hasSecret: !!this.config.secret,
|
|
384
|
+
maxHeaderLength: this.config.maxHeaderLength,
|
|
385
|
+
maxFailedAttempts: this.config.maxFailedAttempts,
|
|
386
|
+
blockDuration: this.config.blockDuration,
|
|
387
|
+
minSecretLength: this.config.minSecretLength,
|
|
388
|
+
timingSafeComparison: this.config.timingSafeComparison,
|
|
389
|
+
rejectSuspiciousPatterns: this.config.rejectSuspiciousPatterns,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Get the header name used for signatures
|
|
394
|
+
*/
|
|
395
|
+
getHeaderName() {
|
|
396
|
+
return this.HEADER_NAME;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Validate if a signature would be accepted (for testing)
|
|
400
|
+
*/
|
|
401
|
+
validateSignature(signature) {
|
|
402
|
+
if (!signature || typeof signature !== "string") {
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
if (!this.validateHeaderLength(signature)) {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
if (this.config.rejectSuspiciousPatterns &&
|
|
409
|
+
this.containsSuspiciousPatterns(signature)) {
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
const processedSignature = this.processSignatureValue(signature);
|
|
413
|
+
const expectedSignature = this.processSignatureValue(this.config.secret);
|
|
414
|
+
return this.compareSignatures(processedSignature, expectedSignature);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Get statistics about failed attempts (for monitoring)
|
|
418
|
+
*/
|
|
419
|
+
getSecurityStats() {
|
|
420
|
+
const now = Date.now();
|
|
421
|
+
let blockedCount = 0;
|
|
422
|
+
for (const attempt of this.failedAttempts.values()) {
|
|
423
|
+
if (attempt.blockedUntil && now < attempt.blockedUntil) {
|
|
424
|
+
blockedCount++;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return {
|
|
428
|
+
trackedClients: this.failedAttempts.size,
|
|
429
|
+
blockedClients: blockedCount,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Cleanup resources
|
|
434
|
+
*/
|
|
435
|
+
destroy() {
|
|
436
|
+
if (this.cleanupTimer) {
|
|
437
|
+
clearInterval(this.cleanupTimer);
|
|
438
|
+
}
|
|
439
|
+
this.failedAttempts.clear();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export { RequestSignatureProtector };
|
|
444
|
+
//# sourceMappingURL=RequestSignatureProtector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestSignatureProtector.js","sources":["../../../../../../src/middleware/built-in/security/RequestSignatureProtector.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|