xypriss 9.6.97 → 9.7.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.
Files changed (171) hide show
  1. package/README.md +55 -22
  2. package/dist/cjs/src/index.js +0 -19
  3. package/dist/cjs/src/index.js.map +1 -1
  4. package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js +4 -4
  5. package/dist/cjs/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
  6. package/dist/cjs/src/middleware/built-in/security/HoneypotTarpit.js +510 -0
  7. package/dist/cjs/src/middleware/built-in/security/HoneypotTarpit.js.map +1 -0
  8. package/dist/cjs/src/middleware/built-in/security/SQLInjectionDetector.js +113 -34
  9. package/dist/cjs/src/middleware/built-in/security/SQLInjectionDetector.js.map +1 -1
  10. package/dist/cjs/src/middleware/built-in/security/UriNormalizer.js +413 -0
  11. package/dist/cjs/src/middleware/built-in/security/UriNormalizer.js.map +1 -0
  12. package/dist/cjs/src/middleware/built-in/security/XyPrissCors.js +98 -0
  13. package/dist/cjs/src/middleware/built-in/security/XyPrissCors.js.map +1 -0
  14. package/dist/cjs/src/middleware/built-in/security/XyPrissHPP.js +52 -0
  15. package/dist/cjs/src/middleware/built-in/security/XyPrissHPP.js.map +1 -0
  16. package/dist/cjs/src/middleware/safe-json-middleware.js +0 -82
  17. package/dist/cjs/src/middleware/safe-json-middleware.js.map +1 -1
  18. package/dist/cjs/src/middleware/security-middleware.js +7 -4
  19. package/dist/cjs/src/middleware/security-middleware.js.map +1 -1
  20. package/dist/cjs/src/plugins/builtin/xems/XemsBuiltinPlugin.js +33 -10
  21. package/dist/cjs/src/plugins/builtin/xems/XemsBuiltinPlugin.js.map +1 -1
  22. package/dist/cjs/src/plugins/builtin/xems/XemsPlugin.js +34 -3
  23. package/dist/cjs/src/plugins/builtin/xems/XemsPlugin.js.map +1 -1
  24. package/dist/cjs/src/plugins/const/OFFICIAL_PLUGINS.js +1 -1
  25. package/dist/cjs/src/plugins/const/OFFICIAL_PLUGINS.js.map +1 -1
  26. package/dist/cjs/src/plugins/const/XyprissTempDir.js +72 -9
  27. package/dist/cjs/src/plugins/const/XyprissTempDir.js.map +1 -1
  28. package/dist/cjs/src/plugins/core/manager/PluginLoader.js +8 -0
  29. package/dist/cjs/src/plugins/core/manager/PluginLoader.js.map +1 -1
  30. package/dist/cjs/src/plugins/core/manager/PluginSecurity.js +87 -0
  31. package/dist/cjs/src/plugins/core/manager/PluginSecurity.js.map +1 -1
  32. package/dist/cjs/src/server/FastServer/index.js +5 -0
  33. package/dist/cjs/src/server/FastServer/index.js.map +1 -1
  34. package/dist/cjs/src/server/ServerFactory.js +8 -13
  35. package/dist/cjs/src/server/ServerFactory.js.map +1 -1
  36. package/dist/cjs/src/server/components/fastapi/RedirectManager.js +8 -58
  37. package/dist/cjs/src/server/components/fastapi/RedirectManager.js.map +1 -1
  38. package/dist/cjs/src/server/components/fastapi/upload/FileUploadManager.js +1 -1
  39. package/dist/cjs/src/server/components/fastapi/upload/FileUploadManager.js.map +1 -1
  40. package/dist/cjs/src/server/components/multi-server/MultiServerManager.js +9 -1
  41. package/dist/cjs/src/server/components/multi-server/MultiServerManager.js.map +1 -1
  42. package/dist/cjs/src/server/core/HttpServer.js +22 -0
  43. package/dist/cjs/src/server/core/HttpServer.js.map +1 -1
  44. package/dist/cjs/src/server/core/XHSCBridge/EngineManager.js +33 -2
  45. package/dist/cjs/src/server/core/XHSCBridge/EngineManager.js.map +1 -1
  46. package/dist/cjs/src/server/core/XHSCBridge/cmd/buildSecurityArgs.js +1 -1
  47. package/dist/cjs/src/server/core/XHSCBridge/cmd/buildSecurityArgs.js.map +1 -1
  48. package/dist/cjs/src/server/core/XyServerCreator.js +1 -0
  49. package/dist/cjs/src/server/core/XyServerCreator.js.map +1 -1
  50. package/dist/cjs/src/shared/logger/quickLogger.js +162 -0
  51. package/dist/cjs/src/shared/logger/quickLogger.js.map +1 -0
  52. package/dist/cjs/src/xhsc/PathApi.js +44 -3
  53. package/dist/cjs/src/xhsc/PathApi.js.map +1 -1
  54. package/dist/cjs/src/xhsc/System.js +2 -0
  55. package/dist/cjs/src/xhsc/System.js.map +1 -1
  56. package/dist/cjs/src/xhsc/UtilsApi.js +52 -0
  57. package/dist/cjs/src/xhsc/UtilsApi.js.map +1 -0
  58. package/dist/cjs/src/xhsc/XyPrissRunner.js +30 -2
  59. package/dist/cjs/src/xhsc/XyPrissRunner.js.map +1 -1
  60. package/dist/cjs/src/xhsc/fs/FSCore.js +148 -0
  61. package/dist/cjs/src/xhsc/fs/FSCore.js.map +1 -1
  62. package/dist/cjs/src/xhsc/fs/FileHandle.js +112 -0
  63. package/dist/cjs/src/xhsc/fs/FileHandle.js.map +1 -0
  64. package/dist/cjs/src/xhsc/ipc/XHSCDirectIPC.js +134 -0
  65. package/dist/cjs/src/xhsc/ipc/XHSCDirectIPC.js.map +1 -0
  66. package/dist/cjs/src/xhsc/utils/ArrayUtils.js +67 -0
  67. package/dist/cjs/src/xhsc/utils/ArrayUtils.js.map +1 -0
  68. package/dist/cjs/src/xhsc/utils/AsyncUtils.js +582 -0
  69. package/dist/cjs/src/xhsc/utils/AsyncUtils.js.map +1 -0
  70. package/dist/cjs/src/xhsc/utils/DateUtils.js +959 -0
  71. package/dist/cjs/src/xhsc/utils/DateUtils.js.map +1 -0
  72. package/dist/cjs/src/xhsc/utils/FunctionUtils.js +29 -0
  73. package/dist/cjs/src/xhsc/utils/FunctionUtils.js.map +1 -0
  74. package/dist/cjs/src/xhsc/utils/IdUtils.js +22 -0
  75. package/dist/cjs/src/xhsc/utils/IdUtils.js.map +1 -0
  76. package/dist/cjs/src/xhsc/utils/NumberUtils.js +79 -0
  77. package/dist/cjs/src/xhsc/utils/NumberUtils.js.map +1 -0
  78. package/dist/cjs/src/xhsc/utils/ObjectUtils.js +141 -0
  79. package/dist/cjs/src/xhsc/utils/ObjectUtils.js.map +1 -0
  80. package/dist/cjs/src/xhsc/utils/StringUtils.js +145 -0
  81. package/dist/cjs/src/xhsc/utils/StringUtils.js.map +1 -0
  82. package/dist/cjs/src/xhsc/utils/ValidationUtils.js +49 -0
  83. package/dist/cjs/src/xhsc/utils/ValidationUtils.js.map +1 -0
  84. package/dist/cjs/src/xhsc.js +5 -3
  85. package/dist/cjs/src/xhsc.js.map +1 -1
  86. package/dist/esm/src/index.js +0 -2
  87. package/dist/esm/src/index.js.map +1 -1
  88. package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js +4 -4
  89. package/dist/esm/src/middleware/built-in/BuiltInMiddleware.js.map +1 -1
  90. package/dist/esm/src/middleware/built-in/security/HoneypotTarpit.js +508 -0
  91. package/dist/esm/src/middleware/built-in/security/HoneypotTarpit.js.map +1 -0
  92. package/dist/esm/src/middleware/built-in/security/SQLInjectionDetector.js +113 -34
  93. package/dist/esm/src/middleware/built-in/security/SQLInjectionDetector.js.map +1 -1
  94. package/dist/esm/src/middleware/built-in/security/UriNormalizer.js +391 -0
  95. package/dist/esm/src/middleware/built-in/security/UriNormalizer.js.map +1 -0
  96. package/dist/esm/src/middleware/built-in/security/XyPrissCors.js +96 -0
  97. package/dist/esm/src/middleware/built-in/security/XyPrissCors.js.map +1 -0
  98. package/dist/esm/src/middleware/built-in/security/XyPrissHPP.js +50 -0
  99. package/dist/esm/src/middleware/built-in/security/XyPrissHPP.js.map +1 -0
  100. package/dist/esm/src/middleware/safe-json-middleware.js +1 -79
  101. package/dist/esm/src/middleware/safe-json-middleware.js.map +1 -1
  102. package/dist/esm/src/middleware/security-middleware.js +7 -4
  103. package/dist/esm/src/middleware/security-middleware.js.map +1 -1
  104. package/dist/esm/src/plugins/builtin/xems/XemsBuiltinPlugin.js +33 -10
  105. package/dist/esm/src/plugins/builtin/xems/XemsBuiltinPlugin.js.map +1 -1
  106. package/dist/esm/src/plugins/builtin/xems/XemsPlugin.js +34 -3
  107. package/dist/esm/src/plugins/builtin/xems/XemsPlugin.js.map +1 -1
  108. package/dist/esm/src/plugins/const/OFFICIAL_PLUGINS.js +1 -1
  109. package/dist/esm/src/plugins/const/OFFICIAL_PLUGINS.js.map +1 -1
  110. package/dist/esm/src/plugins/const/XyprissTempDir.js +70 -9
  111. package/dist/esm/src/plugins/const/XyprissTempDir.js.map +1 -1
  112. package/dist/esm/src/plugins/core/manager/PluginLoader.js +8 -0
  113. package/dist/esm/src/plugins/core/manager/PluginLoader.js.map +1 -1
  114. package/dist/esm/src/plugins/core/manager/PluginSecurity.js +87 -0
  115. package/dist/esm/src/plugins/core/manager/PluginSecurity.js.map +1 -1
  116. package/dist/esm/src/server/FastServer/index.js +5 -0
  117. package/dist/esm/src/server/FastServer/index.js.map +1 -1
  118. package/dist/esm/src/server/ServerFactory.js +8 -1
  119. package/dist/esm/src/server/ServerFactory.js.map +1 -1
  120. package/dist/esm/src/server/components/fastapi/RedirectManager.js +8 -58
  121. package/dist/esm/src/server/components/fastapi/RedirectManager.js.map +1 -1
  122. package/dist/esm/src/server/components/fastapi/upload/FileUploadManager.js +1 -1
  123. package/dist/esm/src/server/components/fastapi/upload/FileUploadManager.js.map +1 -1
  124. package/dist/esm/src/server/components/multi-server/MultiServerManager.js +9 -1
  125. package/dist/esm/src/server/components/multi-server/MultiServerManager.js.map +1 -1
  126. package/dist/esm/src/server/core/HttpServer.js +22 -0
  127. package/dist/esm/src/server/core/HttpServer.js.map +1 -1
  128. package/dist/esm/src/server/core/XHSCBridge/EngineManager.js +33 -2
  129. package/dist/esm/src/server/core/XHSCBridge/EngineManager.js.map +1 -1
  130. package/dist/esm/src/server/core/XHSCBridge/cmd/buildSecurityArgs.js +1 -1
  131. package/dist/esm/src/server/core/XHSCBridge/cmd/buildSecurityArgs.js.map +1 -1
  132. package/dist/esm/src/server/core/XyServerCreator.js +1 -0
  133. package/dist/esm/src/server/core/XyServerCreator.js.map +1 -1
  134. package/dist/esm/src/shared/logger/quickLogger.js +160 -0
  135. package/dist/esm/src/shared/logger/quickLogger.js.map +1 -0
  136. package/dist/esm/src/xhsc/PathApi.js +44 -3
  137. package/dist/esm/src/xhsc/PathApi.js.map +1 -1
  138. package/dist/esm/src/xhsc/System.js +2 -0
  139. package/dist/esm/src/xhsc/System.js.map +1 -1
  140. package/dist/esm/src/xhsc/UtilsApi.js +50 -0
  141. package/dist/esm/src/xhsc/UtilsApi.js.map +1 -0
  142. package/dist/esm/src/xhsc/XyPrissRunner.js +30 -2
  143. package/dist/esm/src/xhsc/XyPrissRunner.js.map +1 -1
  144. package/dist/esm/src/xhsc/fs/FSCore.js +148 -0
  145. package/dist/esm/src/xhsc/fs/FSCore.js.map +1 -1
  146. package/dist/esm/src/xhsc/fs/FileHandle.js +110 -0
  147. package/dist/esm/src/xhsc/fs/FileHandle.js.map +1 -0
  148. package/dist/esm/src/xhsc/ipc/XHSCDirectIPC.js +113 -0
  149. package/dist/esm/src/xhsc/ipc/XHSCDirectIPC.js.map +1 -0
  150. package/dist/esm/src/xhsc/utils/ArrayUtils.js +65 -0
  151. package/dist/esm/src/xhsc/utils/ArrayUtils.js.map +1 -0
  152. package/dist/esm/src/xhsc/utils/AsyncUtils.js +580 -0
  153. package/dist/esm/src/xhsc/utils/AsyncUtils.js.map +1 -0
  154. package/dist/esm/src/xhsc/utils/DateUtils.js +957 -0
  155. package/dist/esm/src/xhsc/utils/DateUtils.js.map +1 -0
  156. package/dist/esm/src/xhsc/utils/FunctionUtils.js +27 -0
  157. package/dist/esm/src/xhsc/utils/FunctionUtils.js.map +1 -0
  158. package/dist/esm/src/xhsc/utils/IdUtils.js +20 -0
  159. package/dist/esm/src/xhsc/utils/IdUtils.js.map +1 -0
  160. package/dist/esm/src/xhsc/utils/NumberUtils.js +77 -0
  161. package/dist/esm/src/xhsc/utils/NumberUtils.js.map +1 -0
  162. package/dist/esm/src/xhsc/utils/ObjectUtils.js +139 -0
  163. package/dist/esm/src/xhsc/utils/ObjectUtils.js.map +1 -0
  164. package/dist/esm/src/xhsc/utils/StringUtils.js +143 -0
  165. package/dist/esm/src/xhsc/utils/StringUtils.js.map +1 -0
  166. package/dist/esm/src/xhsc/utils/ValidationUtils.js +47 -0
  167. package/dist/esm/src/xhsc/utils/ValidationUtils.js.map +1 -0
  168. package/dist/esm/src/xhsc.js +6 -5
  169. package/dist/esm/src/xhsc.js.map +1 -1
  170. package/dist/index.d.ts +1872 -234
  171. package/package.json +119 -137
@@ -0,0 +1,413 @@
1
+ 'use strict';
2
+
3
+ var vm = require('vm');
4
+
5
+ function _interopNamespaceDefault(e) {
6
+ var n = Object.create(null);
7
+ if (e) {
8
+ Object.keys(e).forEach(function (k) {
9
+ if (k !== 'default') {
10
+ var d = Object.getOwnPropertyDescriptor(e, k);
11
+ Object.defineProperty(n, k, d.get ? d : {
12
+ enumerable: true,
13
+ get: function () { return e[k]; }
14
+ });
15
+ }
16
+ });
17
+ }
18
+ n.default = e;
19
+ return Object.freeze(n);
20
+ }
21
+
22
+ var vm__namespace = /*#__PURE__*/_interopNamespaceDefault(vm);
23
+
24
+ /**
25
+ * @module UriNormalizer
26
+ *
27
+ * Normalization and security utilities for URIs and paths.
28
+ *
29
+ * ### Supported Threats
30
+ * - Path traversal (including encoded variants: `%2F`, `%2E`, double-encoded `%2520`)
31
+ * - Injection of null bytes and control characters
32
+ * - ReDoS attacks via sandbox execution with an adaptive timeout
33
+ * - Backslash smuggling (`\..\..\`)
34
+ * - Unicode normalized segments (NFC) to prevent traversal homoglyphs
35
+ *
36
+ * ### Non-regression Guarantees (no false positives)
37
+ * - Legitimate paths with encoded special characters are preserved correctly.
38
+ * - The trailing slash is preserved if present in the original input.
39
+ * - Internal empty segments are cleanly removed (`//` collapse).
40
+ * - The root `/` is always returned for an empty or null input.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * UriNormalizer.normalizePath("/foo/%2E%2E/bar"); // => "/bar"
45
+ * UriNormalizer.normalizePath("/a//b/../c/"); // => "/a/c/"
46
+ * UriNormalizer.safeRegexCheck(/^[a-z]+$/, "hello"); // => true
47
+ * ```
48
+ */
49
+ class UriNormalizer {
50
+ // ─────────────────────────────────────────────────────────────────────────
51
+ // Public API
52
+ // ─────────────────────────────────────────────────────────────────────────
53
+ /**
54
+ * Normalizes a URI path by resolving `.` and `..` segments, multiple
55
+ * slashes, backslashes, null bytes, control characters, and all URI
56
+ * encodings (including double-encodings such as `%2520`).
57
+ *
58
+ * Normalization follows this strict order to eliminate bypass vectors:
59
+ * 1. Iterative decoding until stabilization (anti double-encoding).
60
+ * 2. Unicode NFC normalization (anti homoglyphs).
61
+ * 3. Replacement of backslashes with forward slashes.
62
+ * 4. Removal of null bytes and control characters.
63
+ * 5. Collapse of multiple slashes.
64
+ * 6. Resolution of `.` and `..` segments.
65
+ * 7. Restoration of the trailing slash if the original input had one.
66
+ *
67
+ * ### Guaranteed Behaviors
68
+ * - `""` or `null`/`undefined` → `"/"`
69
+ * - Paths where all segments resolve above the root are clipped
70
+ * to `"/"` (no underflow possible).
71
+ * - The trailing slash is faithfully preserved or removed based on the input.
72
+ * - Unicode control characters (U+0000–U+001F, U+007F–U+009F)
73
+ * are systematically removed.
74
+ *
75
+ * @param {string} pathStr - The raw path to normalize (can be encoded).
76
+ * @returns {string} The normalized path, always prefixed with `/`.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * UriNormalizer.normalizePath("/foo/bar"); // "/foo/bar"
81
+ * UriNormalizer.normalizePath("/foo/../bar"); // "/bar"
82
+ * UriNormalizer.normalizePath("/foo/%2E%2E/bar"); // "/bar"
83
+ * UriNormalizer.normalizePath("/foo/%252E%252E/bar"); // "/bar" (double-encoded)
84
+ * UriNormalizer.normalizePath("/a//b/./c/"); // "/a/b/c/"
85
+ * UriNormalizer.normalizePath("\\foo\\..\\bar"); // "/bar"
86
+ * UriNormalizer.normalizePath("/foo/\0bar"); // "/foo/bar"
87
+ * UriNormalizer.normalizePath(""); // "/"
88
+ * ```
89
+ */
90
+ static normalizePath(pathStr) {
91
+ if (!pathStr)
92
+ return "/";
93
+ // Step 1: Iterative decoding to neutralize double-encodings
94
+ const decoded = UriNormalizer.iterativeDecode(pathStr);
95
+ // Step 2: Unicode NFC normalization
96
+ const nfc = decoded.normalize("NFC");
97
+ // Step 3: Replace backslashes with forward slashes
98
+ const forwardSlashed = nfc.replace(/\\/g, "/");
99
+ // Step 4: Removal of null bytes and control characters
100
+ const sanitized = UriNormalizer.stripControlCharacters(forwardSlashed);
101
+ // Step 5: Collapse multiple slashes (e.g., `///` → `/`)
102
+ const collapsed = sanitized.replace(/\/+/g, "/");
103
+ // Memorize trailing slash before resolution (it will be lost during split)
104
+ const hasTrailingSlash = collapsed.endsWith("/") && collapsed.length > 1;
105
+ // Step 6: Resolve `.` and `..` segments
106
+ const resolved = UriNormalizer.resolveSegments(collapsed);
107
+ // Step 7: Restore trailing slash
108
+ return hasTrailingSlash ? resolved + "/" : resolved;
109
+ }
110
+ /**
111
+ * Executes a regex test with a strict timeout to prevent ReDoS
112
+ * (Regular Expression Denial of Service) attacks.
113
+ *
114
+ * ### Protection Strategy
115
+ * - Short strings (< {@link REGEX_VM_LENGTH_THRESHOLD} characters) are
116
+ * tested directly for performance, but the threshold has been lowered to
117
+ * 20 to cover catastrophic patterns on short repetitions.
118
+ * - Beyond the threshold, the regex is executed in an isolated Node.js VM
119
+ * context with an adaptive timeout calculated by {@link computeRegexTimeout}.
120
+ * - In the event of a timeout or VM error, the method returns `false` **and**
121
+ * throws a typed error to distinguish a real ReDoS from a false positive.
122
+ *
123
+ * ### Error Differentiation
124
+ * - `UriNormalizerRegexTimeoutError`: timeout reached → probable ReDoS.
125
+ * - Any other internal exception is propagated as-is to avoid hiding
126
+ * caller layer bugs.
127
+ *
128
+ * @param {RegExp} pattern - The regular expression to evaluate.
129
+ * @param {string} str - The string to test against.
130
+ * @param {number} [timeoutMs] - Base timeout in ms (default: {@link REGEX_BASE_TIMEOUT_MS}).
131
+ * Automatically increased based on `str` length.
132
+ * @returns {boolean} `true` if the regex matches, `false` otherwise or on timeout.
133
+ * @throws {TypeError} If `pattern` is not a RegExp instance.
134
+ * @throws {UriNormalizerRegexTimeoutError} If the VM timeout is reached (probable ReDoS).
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * // Basic usage
139
+ * UriNormalizer.safeRegexCheck(/^[a-z]+$/, "hello"); // true
140
+ * UriNormalizer.safeRegexCheck(/^[a-z]+$/, "Hello"); // false
141
+ *
142
+ * // Potentially catastrophic pattern on long input
143
+ * try {
144
+ * UriNormalizer.safeRegexCheck(/(a+)+$/, "a".repeat(5000) + "!");
145
+ * } catch (e) {
146
+ * if (e instanceof UriNormalizerRegexTimeoutError) {
147
+ * console.warn("ReDoS blocked: ", e.message);
148
+ * }
149
+ * }
150
+ * ```
151
+ */
152
+ static safeRegexCheck(pattern, str, timeoutMs = UriNormalizer.REGEX_BASE_TIMEOUT_MS) {
153
+ // Strict pattern validation for a clear error message
154
+ if (!(pattern instanceof RegExp)) {
155
+ throw new TypeError(`UriNormalizer.safeRegexCheck: "pattern" must be an instance of RegExp, received: ${typeof pattern}`);
156
+ }
157
+ // Fast path for very short strings (negligible ReDoS risk)
158
+ if (str.length < UriNormalizer.REGEX_VM_LENGTH_THRESHOLD) {
159
+ return pattern.test(str);
160
+ }
161
+ // Calculate adaptive timeout
162
+ const effectiveTimeout = UriNormalizer.computeRegexTimeout(str.length, timeoutMs);
163
+ try {
164
+ const sandbox = { result: false, pattern, str };
165
+ const context = vm__namespace.createContext(sandbox);
166
+ vm__namespace.runInContext("result = pattern.test(str)", context, {
167
+ timeout: effectiveTimeout,
168
+ });
169
+ return sandbox.result;
170
+ }
171
+ catch (e) {
172
+ // Distinguish a VM timeout from an unexpected error
173
+ if (UriNormalizer.isVmTimeoutError(e)) {
174
+ throw new UriNormalizerRegexTimeoutError(`Regex exceeded timeout (${effectiveTimeout}ms) on an input of ${str.length} characters. Possible ReDoS.`, effectiveTimeout, str.length);
175
+ }
176
+ // Propagate any other VM error (e.g., internal syntax error)
177
+ throw e;
178
+ }
179
+ }
180
+ // ─────────────────────────────────────────────────────────────────────────
181
+ // Private Methods — URI Decoding
182
+ // ─────────────────────────────────────────────────────────────────────────
183
+ /**
184
+ * Iteratively decodes a URI path until it is stable (idempotent),
185
+ * neutralizing double-encodings and cascading encodings.
186
+ *
187
+ * **Example of bypass without this protection:**
188
+ * ```
189
+ * %2520 → (1st decode) %20 → (2nd decode) " "
190
+ * %252E%252E → %2E%2E → .. ← hidden traversal
191
+ * ```
192
+ *
193
+ * The loop is bounded to {@link MAX_DECODE_ITERATIONS} to prevent any
194
+ * infinite loop on pathological synthetic inputs. If the limit is reached,
195
+ * the last stable state is returned without throwing an exception.
196
+ *
197
+ * @param {string} raw - The raw string, potentially multi-encoded.
198
+ * @returns {string} The fully decoded string.
199
+ *
200
+ * @private
201
+ */
202
+ static iterativeDecode(raw) {
203
+ let current = raw;
204
+ for (let i = 0; i < UriNormalizer.MAX_DECODE_ITERATIONS; i++) {
205
+ let next;
206
+ try {
207
+ next = decodeURIComponent(current);
208
+ }
209
+ catch {
210
+ // Malformed URI (e.g., `%GG`): abort and keep previous state
211
+ break;
212
+ }
213
+ if (next === current) {
214
+ // Idempotence reached: decoding is stable
215
+ break;
216
+ }
217
+ current = next;
218
+ }
219
+ return current;
220
+ }
221
+ // ─────────────────────────────────────────────────────────────────────────
222
+ // Private Methods — String Sanitization
223
+ // ─────────────────────────────────────────────────────────────────────────
224
+ /**
225
+ * Strips all ASCII and Unicode control characters from a string.
226
+ *
227
+ * The removed ranges are:
228
+ * - U+0000–U+001F: C0 control characters (including null byte, tab, LF, CR...)
229
+ * - U+007F : DEL
230
+ * - U+0080–U+009F: C1 control characters
231
+ *
232
+ * These characters can be exploited to bypass filters relying on naive
233
+ * string comparisons or to cause unexpected behavior in downstream parsers
234
+ * (e.g., HTTP servers, file systems).
235
+ *
236
+ * @param {string} str - The string to sanitize.
237
+ * @returns {string} The string without control characters.
238
+ *
239
+ * @private
240
+ */
241
+ static stripControlCharacters(str) {
242
+ // eslint-disable-next-line no-control-regex
243
+ return str.replace(/[\u0000-\u001F\u007F-\u009F]/g, "");
244
+ }
245
+ // ─────────────────────────────────────────────────────────────────────────
246
+ // Private Methods — Segment Resolution
247
+ // ─────────────────────────────────────────────────────────────────────────
248
+ /**
249
+ * Resolves `.` (current directory) and `..` (parent directory) segments
250
+ * from a normalized path (without double-slashes or residual encodings).
251
+ *
252
+ * The stack can never go below the root: a `..` at the head of the path
253
+ * is silently ignored, preventing any underflow to `../`.
254
+ *
255
+ * @param {string} path - The pre-normalized path (consolidated slashes, decoded).
256
+ * @returns {string} The path with all `.` and `..` segments resolved,
257
+ * always prefixed by `/`.
258
+ *
259
+ * @example
260
+ * ```ts
261
+ * // (private method — internal illustration)
262
+ * resolveSegments("/a/b/../../c") // "/c"
263
+ * resolveSegments("/../../../etc") // "/etc" ← no underflow
264
+ * resolveSegments("/a/./b") // "/a/b"
265
+ * ```
266
+ *
267
+ * @private
268
+ */
269
+ static resolveSegments(path) {
270
+ const parts = path.split("/");
271
+ const stack = [];
272
+ for (const segment of parts) {
273
+ if (segment === "..") {
274
+ // Never exceed root (anti-underflow)
275
+ if (stack.length > 0) {
276
+ stack.pop();
277
+ }
278
+ }
279
+ else if (segment !== "." && segment !== "") {
280
+ stack.push(segment);
281
+ }
282
+ }
283
+ return "/" + stack.join("/");
284
+ }
285
+ // ─────────────────────────────────────────────────────────────────────────
286
+ // Private Methods — ReDoS / VM Utilities
287
+ // ─────────────────────────────────────────────────────────────────────────
288
+ /**
289
+ * Calculates an adaptive timeout for executing a regex in the VM sandbox,
290
+ * adding a delta proportional to the length of the string being tested.
291
+ *
292
+ * ### Formula
293
+ * ```
294
+ * timeout = min(baseMs + floor(length / 1000) * PER_1K, MAX_TIMEOUT)
295
+ * ```
296
+ *
297
+ * This avoids false positives on long legitimate inputs while maintaining
298
+ * a hard ceiling ({@link REGEX_MAX_TIMEOUT_MS}) to contain severe ReDoS.
299
+ *
300
+ * @param {number} length - Length of the tested string.
301
+ * @param {number} baseMs - Base timeout provided by the caller.
302
+ * @returns {number} The effective timeout in milliseconds.
303
+ *
304
+ * @private
305
+ */
306
+ static computeRegexTimeout(length, baseMs) {
307
+ const delta = Math.floor(length / 1000) *
308
+ UriNormalizer.REGEX_TIMEOUT_PER_1K_CHARS;
309
+ return Math.min(baseMs + delta, UriNormalizer.REGEX_MAX_TIMEOUT_MS);
310
+ }
311
+ /**
312
+ * Determines whether an error thrown by `vm.runInContext` is a timeout
313
+ * overrun (i.e. a Node.js script interruption).
314
+ *
315
+ * Node.js does not provide a dedicated error class for this type of error.
316
+ * Detection relies on the `ERR_SCRIPT_EXECUTION_TIMEOUT` error code and/or
317
+ * the error message (`"Script execution timed out"`), which are stable since Node 10.
318
+ *
319
+ * @param {unknown} error - The exception to inspect.
320
+ * @returns {boolean} `true` if the error is a VM timeout, `false` otherwise.
321
+ *
322
+ * @private
323
+ */
324
+ static isVmTimeoutError(error) {
325
+ if (!(error instanceof Error))
326
+ return false;
327
+ const nodeError = error;
328
+ if (nodeError.code === "ERR_SCRIPT_EXECUTION_TIMEOUT")
329
+ return true;
330
+ // Fallback to the message for older Node versions
331
+ return error.message.toLowerCase().includes("timed out");
332
+ }
333
+ }
334
+ // ─────────────────────────────────────────────────────────────────────────
335
+ // Private Constants
336
+ // ─────────────────────────────────────────────────────────────────────────
337
+ /**
338
+ * Maximum number of URI decoding iterations to stop infinite loops
339
+ * on pathological inputs (e.g., synthetic infinite encodings).
340
+ */
341
+ UriNormalizer.MAX_DECODE_ITERATIONS = 10;
342
+ /**
343
+ * Minimum length (inclusive) from which regex execution is deferred
344
+ * to an isolated VM context with a timeout, regardless of the apparent
345
+ * complexity of the pattern.
346
+ *
347
+ * Lowered to 20 chars to cover catastrophic patterns on short
348
+ * repetitive inputs (e.g., `(a+)+` tested on `"aaaaaaaaaaaaaaaab"`).
349
+ */
350
+ UriNormalizer.REGEX_VM_LENGTH_THRESHOLD = 20;
351
+ /**
352
+ * Base VM timeout in milliseconds. It is proportionally increased
353
+ * according to the string length to avoid false positives on long
354
+ * legitimate inputs while keeping a hard limit on ReDoS.
355
+ *
356
+ * @see {@link UriNormalizer.computeRegexTimeout}
357
+ */
358
+ UriNormalizer.REGEX_BASE_TIMEOUT_MS = 50;
359
+ /**
360
+ * Multiplicative factor (ms per 1,000 characters) added to the base
361
+ * timeout for long strings. This prevents false positives on large
362
+ * legitimate inputs.
363
+ */
364
+ UriNormalizer.REGEX_TIMEOUT_PER_1K_CHARS = 5;
365
+ /**
366
+ * Absolute ceiling for the VM timeout in milliseconds to prevent
367
+ * a massive input from rendering the timeout useless.
368
+ */
369
+ UriNormalizer.REGEX_MAX_TIMEOUT_MS = 200;
370
+ // ─────────────────────────────────────────────────────────────────────────────
371
+ // Custom Errors
372
+ // ─────────────────────────────────────────────────────────────────────────────
373
+ /**
374
+ * Error thrown by {@link UriNormalizer.safeRegexCheck} when regex execution
375
+ * in the VM context exceeds the allocated timeout.
376
+ *
377
+ * This error allows the calling layer to distinguish a true ReDoS block
378
+ * from a legitimate `false` return (normal non-match), and to apply an
379
+ * appropriate security policy (log, alert, block the request...).
380
+ *
381
+ * @extends {Error}
382
+ *
383
+ * @example
384
+ * ```ts
385
+ * try {
386
+ * UriNormalizer.safeRegexCheck(/(a+)+$/, "a".repeat(10_000) + "!");
387
+ * } catch (e) {
388
+ * if (e instanceof UriNormalizerRegexTimeoutError) {
389
+ * console.error(`ReDoS detected (timeout=${e.timeoutMs}ms, len=${e.inputLength})`);
390
+ * }
391
+ * }
392
+ * ```
393
+ */
394
+ class UriNormalizerRegexTimeoutError extends Error {
395
+ /**
396
+ * @param {string} message - Descriptive error message.
397
+ * @param {number} timeoutMs - Exceeded effective timeout.
398
+ * @param {number} inputLength - Length of the tested input.
399
+ */
400
+ constructor(message, timeoutMs, inputLength) {
401
+ super(message);
402
+ /** Class name for reliable instanceof and logging. */
403
+ this.name = "UriNormalizerRegexTimeoutError";
404
+ this.timeoutMs = timeoutMs;
405
+ this.inputLength = inputLength;
406
+ // Proper prototype chain restoration in TypeScript/Babel
407
+ Object.setPrototypeOf(this, new.target.prototype);
408
+ }
409
+ }
410
+
411
+ exports.UriNormalizer = UriNormalizer;
412
+ exports.UriNormalizerRegexTimeoutError = UriNormalizerRegexTimeoutError;
413
+ //# sourceMappingURL=UriNormalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UriNormalizer.js","sources":["../../../../../../src/middleware/built-in/security/UriNormalizer.ts"],"sourcesContent":[null],"names":["vm"],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ 'use strict';
2
+
3
+ function xyprissCors(options = {}) {
4
+ const defaultOptions = {
5
+ origin: true,
6
+ methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
7
+ preflightContinue: false,
8
+ optionsSuccessStatus: 204,
9
+ };
10
+ const config = Object.assign({}, defaultOptions, options);
11
+ return function corsMiddleware(req, res, next) {
12
+ const currentOrigin = req.headers ? req.headers.origin : undefined;
13
+ const appendVary = (headerStr, field) => {
14
+ if (headerStr === "*")
15
+ return headerStr;
16
+ const parts = headerStr.split(",").map((s) => s.trim());
17
+ if (!parts.includes(field)) {
18
+ parts.push(field);
19
+ }
20
+ return parts.join(", ");
21
+ };
22
+ const applyHeaders = (originAllowed) => {
23
+ if (originAllowed === true || originAllowed === "*") {
24
+ res.setHeader("Access-Control-Allow-Origin", "*");
25
+ }
26
+ else if (typeof originAllowed === "string") {
27
+ res.setHeader("Access-Control-Allow-Origin", originAllowed);
28
+ const vary = res.getHeader("Vary") || "";
29
+ res.setHeader("Vary", appendVary(String(vary), "Origin"));
30
+ }
31
+ if (config.credentials) {
32
+ res.setHeader("Access-Control-Allow-Credentials", "true");
33
+ }
34
+ if (config.exposedHeaders) {
35
+ const eh = Array.isArray(config.exposedHeaders)
36
+ ? config.exposedHeaders.join(",")
37
+ : config.exposedHeaders;
38
+ res.setHeader("Access-Control-Expose-Headers", eh);
39
+ }
40
+ if (req.method === "OPTIONS") {
41
+ if (config.methods) {
42
+ const m = Array.isArray(config.methods)
43
+ ? config.methods.join(",")
44
+ : config.methods;
45
+ res.setHeader("Access-Control-Allow-Methods", m);
46
+ }
47
+ if (config.allowedHeaders) {
48
+ const ah = Array.isArray(config.allowedHeaders)
49
+ ? config.allowedHeaders.join(",")
50
+ : config.allowedHeaders;
51
+ res.setHeader("Access-Control-Allow-Headers", ah);
52
+ }
53
+ else if (req.headers &&
54
+ req.headers["access-control-request-headers"]) {
55
+ res.setHeader("Access-Control-Allow-Headers", req.headers["access-control-request-headers"]);
56
+ const vary = res.getHeader("Vary") || "";
57
+ res.setHeader("Vary", appendVary(String(vary), "Access-Control-Request-Headers"));
58
+ }
59
+ if (config.maxAge !== undefined && config.maxAge !== null) {
60
+ res.setHeader("Access-Control-Max-Age", String(config.maxAge));
61
+ }
62
+ if (!config.preflightContinue) {
63
+ res.statusCode = config.optionsSuccessStatus || 204;
64
+ // For typical frameworks setting Content-Length to 0 is cleanly handled
65
+ res.setHeader("Content-Length", "0");
66
+ res.end();
67
+ return;
68
+ }
69
+ }
70
+ next();
71
+ };
72
+ if (typeof config.origin === "function") {
73
+ const originFn = config.origin;
74
+ originFn(currentOrigin, (err, allow) => {
75
+ if (err)
76
+ return next(err);
77
+ if (allow) {
78
+ applyHeaders(allow);
79
+ }
80
+ else {
81
+ next();
82
+ }
83
+ });
84
+ }
85
+ else if (config.origin === true || config.origin === "*") {
86
+ applyHeaders("*");
87
+ }
88
+ else if (typeof config.origin === "string") {
89
+ applyHeaders(config.origin);
90
+ }
91
+ else {
92
+ next();
93
+ }
94
+ };
95
+ }
96
+
97
+ exports.xyprissCors = xyprissCors;
98
+ //# sourceMappingURL=XyPrissCors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XyPrissCors.js","sources":["../../../../../../src/middleware/built-in/security/XyPrissCors.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ function xyprissHPP(options = {}) {
4
+ const checkQuery = options.checkQuery !== false;
5
+ const checkBody = options.checkBody !== false;
6
+ const whitelist = Array.isArray(options.whitelist)
7
+ ? options.whitelist.filter((w) => typeof w === "string")
8
+ : [];
9
+ function putAside(req, keyReqPart, keyPolluted) {
10
+ const reqPart = req[keyReqPart];
11
+ if (!reqPart || typeof reqPart !== "object")
12
+ return;
13
+ let reqPolluted = req[keyPolluted];
14
+ if (reqPolluted === undefined) {
15
+ reqPolluted = req[keyPolluted] = {};
16
+ const parameters = Object.keys(reqPart);
17
+ for (let i = 0; i < parameters.length; i++) {
18
+ const paramKey = parameters[i];
19
+ const paramValue = reqPart[paramKey];
20
+ if (!Array.isArray(paramValue)) {
21
+ continue;
22
+ }
23
+ reqPolluted[paramKey] = paramValue;
24
+ // Prends le dernier élément du tableau pour éviter la pollution de variables multiples
25
+ reqPart[paramKey] = paramValue[paramValue.length - 1];
26
+ }
27
+ }
28
+ if (whitelist.length > 0) {
29
+ for (let k = 0; k < whitelist.length; k++) {
30
+ const whitelistedParam = whitelist[k];
31
+ if (reqPolluted[whitelistedParam]) {
32
+ reqPart[whitelistedParam] = reqPolluted[whitelistedParam];
33
+ delete reqPolluted[whitelistedParam];
34
+ }
35
+ }
36
+ }
37
+ }
38
+ return function hppMiddleware(req, res, next) {
39
+ if (checkQuery && req.query) {
40
+ putAside(req, "query", "queryPolluted");
41
+ }
42
+ if (checkBody && req.body) {
43
+ // Optionnellement, vérifier le header Content-Type pour url-encoded ou autres formats
44
+ // mais ici on s'aligne globalement sur ce qui a déjà été parsé.
45
+ putAside(req, "body", "bodyPolluted");
46
+ }
47
+ next();
48
+ };
49
+ }
50
+
51
+ exports.xyprissHPP = xyprissHPP;
52
+ //# sourceMappingURL=XyPrissHPP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XyPrissHPP.js","sources":["../../../../../../src/middleware/built-in/security/XyPrissHPP.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAMM,SAAU,UAAU,CAAC,OAAA,GAA6B,EAAE,EAAA;AACtD,IAAA,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,KAAK,KAAK;AAC/C,IAAA,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,KAAK,KAAK;IAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS;AAC7C,UAAE,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,QAAQ;UACrD,EAAE;AAER,IAAA,SAAS,QAAQ,CAAC,GAAQ,EAAE,UAAkB,EAAE,WAAmB,EAAA;AAC/D,QAAA,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC;AAC/B,QAAA,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE;AAE7C,QAAA,IAAI,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;AAElC,QAAA,IAAI,WAAW,KAAK,SAAS,EAAE;AAC3B,YAAA,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE;YAEnC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AACvC,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACxC,gBAAA,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC;AAC9B,gBAAA,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC;gBAEpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;oBAC5B;gBACJ;AAEA,gBAAA,WAAW,CAAC,QAAQ,CAAC,GAAG,UAAU;;AAElC,gBAAA,OAAO,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;YACzD;QACJ;AAEA,QAAA,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AACtB,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACvC,gBAAA,MAAM,gBAAgB,GAAG,SAAS,CAAC,CAAC,CAAC;AACrC,gBAAA,IAAI,WAAW,CAAC,gBAAgB,CAAC,EAAE;oBAC/B,OAAO,CAAC,gBAAgB,CAAC,GAAG,WAAW,CAAC,gBAAgB,CAAC;AACzD,oBAAA,OAAO,WAAW,CAAC,gBAAgB,CAAC;gBACxC;YACJ;QACJ;IACJ;AAEA,IAAA,OAAO,SAAS,aAAa,CAAC,GAAQ,EAAE,GAAQ,EAAE,IAAS,EAAA;AACvD,QAAA,IAAI,UAAU,IAAI,GAAG,CAAC,KAAK,EAAE;AACzB,YAAA,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,eAAe,CAAC;QAC3C;AAEA,QAAA,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE;;;AAGvB,YAAA,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC;QACzC;AAEA,QAAA,IAAI,EAAE;AACV,IAAA,CAAC;AACL;;;;"}