axiodb 21.7.8 → 22.2.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/lib/Helper/Console.helper.js +0 -1
- package/lib/Helper/Converter.helper.js +0 -1
- package/lib/Helper/DocumentLoader.helper.js +0 -1
- package/lib/Helper/Logger.helper.js +0 -1
- package/lib/Helper/PathSanitizer.helper.js +0 -1
- package/lib/Helper/RegexGuard.helper.d.ts +85 -0
- package/lib/Helper/RegexGuard.helper.js +277 -0
- package/lib/Helper/SafeErrorMessage.helper.d.ts +18 -0
- package/lib/Helper/SafeErrorMessage.helper.js +41 -0
- package/lib/Helper/SortedIndexValues.helper.js +0 -1
- package/lib/Helper/UniqueGenerator.helper.js +0 -1
- package/lib/Helper/response.helper.js +0 -1
- package/lib/Memory/memory.operation.js +0 -1
- package/lib/Services/Aggregation/Aggregation.Operation.js +0 -1
- package/lib/Services/Aggregation/OperatorRegistry.js +0 -1
- package/lib/Services/Aggregation/operators/accumulatorOperators.js +0 -1
- package/lib/Services/Aggregation/operators/expressionOperators.js +5 -2
- package/lib/Services/Aggregation/operators/stageOperators.js +5 -2
- package/lib/Services/Auth/AuthEvents.service.js +0 -1
- package/lib/Services/Auth/AuthSeeder.service.js +0 -1
- package/lib/Services/Auth/AuthService.service.js +0 -1
- package/lib/Services/Auth/ConfigDatabase.service.js +0 -1
- package/lib/Services/Auth/CookieCodec.helper.js +0 -1
- package/lib/Services/Auth/LoginRateLimiter.service.js +0 -1
- package/lib/Services/Auth/PasswordHasher.helper.js +0 -1
- package/lib/Services/Auth/PermissionChecker.helper.js +0 -1
- package/lib/Services/Auth/SessionStore.service.js +0 -1
- package/lib/Services/CRUD Operation/Create.operation.js +0 -1
- package/lib/Services/CRUD Operation/Delete.operation.js +0 -1
- package/lib/Services/CRUD Operation/Reader.operation.js +0 -1
- package/lib/Services/CRUD Operation/Update.operation.js +0 -1
- package/lib/Services/Collection/collection.operation.js +0 -1
- package/lib/Services/Database/database.operation.js +2 -3
- package/lib/Services/Index/Index.service.js +0 -1
- package/lib/Services/Index/IndexCache.service.js +0 -1
- package/lib/Services/Index/ReadIndex.service.js +0 -1
- package/lib/Services/Indexation.operation.js +4 -4
- package/lib/Services/Transaction/LockManager.service.js +0 -1
- package/lib/Services/Transaction/Session.service.js +0 -1
- package/lib/Services/Transaction/Transaction.service.js +0 -1
- package/lib/Services/Transaction/TransactionIndexManager.service.js +0 -1
- package/lib/Services/Transaction/TransactionRegistry.service.js +0 -1
- package/lib/Services/Transaction/WriteAheadLog.service.js +0 -1
- package/lib/client/AggregationProxy.js +0 -1
- package/lib/client/AxioDBCloud.client.js +0 -1
- package/lib/client/CollectionProxy.js +0 -1
- package/lib/client/DatabaseProxy.js +0 -1
- package/lib/client/DeleteOperationProxy.js +0 -1
- package/lib/client/PooledConnection.js +0 -1
- package/lib/client/ReaderProxy.js +0 -1
- package/lib/client/TransactionProxy.js +0 -1
- package/lib/client/UpdateOperationProxy.js +0 -1
- package/lib/client/types/client.types.js +0 -1
- package/lib/config/DB.js +0 -1
- package/lib/config/Interfaces/Auth/auth.interface.js +0 -1
- package/lib/config/Interfaces/Helper/response.helper.interface.js +0 -1
- package/lib/config/Interfaces/Operation/Indexation.operation.interface.js +0 -1
- package/lib/config/Interfaces/Operation/aggregation.interface.js +0 -1
- package/lib/config/Interfaces/Operation/database.operation.interface.js +0 -1
- package/lib/config/Interfaces/Transaction/transaction.interface.js +0 -1
- package/lib/config/Interfaces/shared.types.js +0 -1
- package/lib/config/Keys/Keys.js +0 -1
- package/lib/config/Keys/Permissions.js +0 -1
- package/lib/config/Keys/StatusCode.js +0 -1
- package/lib/engine/Filesystem/FileManager.js +9 -4
- package/lib/engine/Filesystem/FolderManager.js +8 -3
- package/lib/engine/node/WorkerForDataLoad.engine.js +0 -1
- package/lib/engine/node/WorkerForSearch.engine.js +0 -1
- package/lib/server/config/PortFreeChecker.js +0 -1
- package/lib/server/config/keys.d.ts +6 -0
- package/lib/server/config/keys.js +14 -2
- package/lib/server/config/server.js +5 -1
- package/lib/server/controller/Auth/Auth.controller.js +0 -1
- package/lib/server/controller/Auth/RoleManagement.controller.js +0 -1
- package/lib/server/controller/Auth/UserManagement.controller.js +0 -1
- package/lib/server/controller/Collections/Collection.controller.js +0 -1
- package/lib/server/controller/Database/Databse.controller.js +2 -2
- package/lib/server/controller/Index/Index.controller.js +0 -1
- package/lib/server/controller/Operation/CRUD.controller.js +0 -1
- package/lib/server/controller/Stats.controller.js +0 -1
- package/lib/server/helper/databaseImport.helper.js +0 -1
- package/lib/server/helper/documentCounterInFolder.helper.js +0 -1
- package/lib/server/helper/responseBuilder.helper.js +0 -1
- package/lib/server/middleware/auth.middleware.js +0 -1
- package/lib/server/middleware/permission.middleware.js +0 -1
- package/lib/server/public/AxioControl/AXioDB.png +0 -0
- package/lib/server/public/AxioControl/assets/index-B9AO8c4G.js +1 -0
- package/lib/server/public/AxioControl/index.html +1 -1
- package/lib/server/public/AxioControl/sw.js +1 -1
- package/lib/server/public/DONT_TOUCH_THIS_FILE.js +0 -1
- package/lib/server/router/Router.js +0 -1
- package/lib/server/router/Routers/Auth.routes.js +0 -1
- package/lib/server/router/Routers/Collection.routes.js +0 -1
- package/lib/server/router/Routers/DB.routes.js +0 -1
- package/lib/server/router/Routers/Index.routes.js +0 -1
- package/lib/server/router/Routers/Operation.routes.js +0 -1
- package/lib/server/router/Routers/RoleManagement.routes.js +0 -1
- package/lib/server/router/Routers/UserManagement.routes.js +0 -1
- package/lib/tcp/config/keys.js +0 -1
- package/lib/tcp/config/permissions.js +0 -1
- package/lib/tcp/config/protocol.js +0 -1
- package/lib/tcp/config/server.js +2 -2
- package/lib/tcp/connection/ConnectionManager.js +2 -2
- package/lib/tcp/connection/ConnectionRateLimiter.js +0 -1
- package/lib/tcp/connection/RequestContext.js +0 -1
- package/lib/tcp/connection/TransactionManager.js +0 -1
- package/lib/tcp/handler/CommandHandler.js +3 -3
- package/lib/tcp/handler/handlers/Auth.handler.js +0 -1
- package/lib/tcp/handler/handlers/Collection.handler.d.ts +1 -1
- package/lib/tcp/handler/handlers/Collection.handler.js +6 -6
- package/lib/tcp/handler/handlers/DB.handler.js +5 -5
- package/lib/tcp/handler/handlers/Operation.handler.js +3 -2
- package/lib/tcp/handler/handlers/Transaction.handler.js +3 -2
- package/lib/tcp/types/command.types.js +0 -1
- package/lib/tcp/types/protocol.types.js +0 -1
- package/lib/utility/BufferLoaderWithWorker.utils.js +0 -1
- package/lib/utility/Searcher.utils.js +3 -3
- package/lib/utility/SortData.utils.js +0 -1
- package/lib/utility/ZipUnzip.utils.js +0 -1
- package/package.json +1 -1
- package/.commandcode/settings.json +0 -24
- package/.commandcode/taste/taste.md +0 -2
- package/.commandcode/taste/user-taste-profile/taste.md +0 -39
- package/lib/Helper/Console.helper.js.map +0 -1
- package/lib/Helper/Converter.helper.js.map +0 -1
- package/lib/Helper/DocumentLoader.helper.js.map +0 -1
- package/lib/Helper/Logger.helper.js.map +0 -1
- package/lib/Helper/PathSanitizer.helper.js.map +0 -1
- package/lib/Helper/SortedIndexValues.helper.js.map +0 -1
- package/lib/Helper/UniqueGenerator.helper.js.map +0 -1
- package/lib/Helper/response.helper.js.map +0 -1
- package/lib/Memory/memory.operation.js.map +0 -1
- package/lib/Services/Aggregation/Aggregation.Operation.js.map +0 -1
- package/lib/Services/Aggregation/OperatorRegistry.js.map +0 -1
- package/lib/Services/Aggregation/operators/accumulatorOperators.js.map +0 -1
- package/lib/Services/Aggregation/operators/expressionOperators.js.map +0 -1
- package/lib/Services/Aggregation/operators/stageOperators.js.map +0 -1
- package/lib/Services/Auth/AuthEvents.service.js.map +0 -1
- package/lib/Services/Auth/AuthSeeder.service.js.map +0 -1
- package/lib/Services/Auth/AuthService.service.js.map +0 -1
- package/lib/Services/Auth/ConfigDatabase.service.js.map +0 -1
- package/lib/Services/Auth/CookieCodec.helper.js.map +0 -1
- package/lib/Services/Auth/LoginRateLimiter.service.js.map +0 -1
- package/lib/Services/Auth/PasswordHasher.helper.js.map +0 -1
- package/lib/Services/Auth/PermissionChecker.helper.js.map +0 -1
- package/lib/Services/Auth/SessionStore.service.js.map +0 -1
- package/lib/Services/CRUD Operation/Create.operation.js.map +0 -1
- package/lib/Services/CRUD Operation/Delete.operation.js.map +0 -1
- package/lib/Services/CRUD Operation/Reader.operation.js.map +0 -1
- package/lib/Services/CRUD Operation/Update.operation.js.map +0 -1
- package/lib/Services/Collection/collection.operation.js.map +0 -1
- package/lib/Services/Database/database.operation.js.map +0 -1
- package/lib/Services/Index/Index.service.js.map +0 -1
- package/lib/Services/Index/IndexCache.service.js.map +0 -1
- package/lib/Services/Index/ReadIndex.service.js.map +0 -1
- package/lib/Services/Indexation.operation.js.map +0 -1
- package/lib/Services/Transaction/LockManager.service.js.map +0 -1
- package/lib/Services/Transaction/Session.service.js.map +0 -1
- package/lib/Services/Transaction/Transaction.service.js.map +0 -1
- package/lib/Services/Transaction/TransactionIndexManager.service.js.map +0 -1
- package/lib/Services/Transaction/TransactionRegistry.service.js.map +0 -1
- package/lib/Services/Transaction/WriteAheadLog.service.js.map +0 -1
- package/lib/client/AggregationProxy.js.map +0 -1
- package/lib/client/AxioDBCloud.client.js.map +0 -1
- package/lib/client/CollectionProxy.js.map +0 -1
- package/lib/client/DatabaseProxy.js.map +0 -1
- package/lib/client/DeleteOperationProxy.js.map +0 -1
- package/lib/client/PooledConnection.js.map +0 -1
- package/lib/client/ReaderProxy.js.map +0 -1
- package/lib/client/TransactionProxy.js.map +0 -1
- package/lib/client/UpdateOperationProxy.js.map +0 -1
- package/lib/client/types/client.types.js.map +0 -1
- package/lib/config/DB.js.map +0 -1
- package/lib/config/Interfaces/Auth/auth.interface.js.map +0 -1
- package/lib/config/Interfaces/Helper/response.helper.interface.js.map +0 -1
- package/lib/config/Interfaces/Operation/Indexation.operation.interface.js.map +0 -1
- package/lib/config/Interfaces/Operation/aggregation.interface.js.map +0 -1
- package/lib/config/Interfaces/Operation/database.operation.interface.js.map +0 -1
- package/lib/config/Interfaces/Transaction/transaction.interface.js.map +0 -1
- package/lib/config/Interfaces/shared.types.js.map +0 -1
- package/lib/config/Keys/Keys.js.map +0 -1
- package/lib/config/Keys/Permissions.js.map +0 -1
- package/lib/config/Keys/StatusCode.js.map +0 -1
- package/lib/engine/Filesystem/FileManager.js.map +0 -1
- package/lib/engine/Filesystem/FolderManager.js.map +0 -1
- package/lib/engine/node/WorkerForDataLoad.engine.js.map +0 -1
- package/lib/engine/node/WorkerForSearch.engine.js.map +0 -1
- package/lib/server/config/PortFreeChecker.js.map +0 -1
- package/lib/server/config/keys.js.map +0 -1
- package/lib/server/config/server.js.map +0 -1
- package/lib/server/controller/Auth/Auth.controller.js.map +0 -1
- package/lib/server/controller/Auth/RoleManagement.controller.js.map +0 -1
- package/lib/server/controller/Auth/UserManagement.controller.js.map +0 -1
- package/lib/server/controller/Collections/Collection.controller.js.map +0 -1
- package/lib/server/controller/Database/Databse.controller.js.map +0 -1
- package/lib/server/controller/Index/Index.controller.js.map +0 -1
- package/lib/server/controller/Operation/CRUD.controller.js.map +0 -1
- package/lib/server/controller/Stats.controller.js.map +0 -1
- package/lib/server/helper/databaseImport.helper.js.map +0 -1
- package/lib/server/helper/documentCounterInFolder.helper.js.map +0 -1
- package/lib/server/helper/responseBuilder.helper.js.map +0 -1
- package/lib/server/middleware/auth.middleware.js.map +0 -1
- package/lib/server/middleware/permission.middleware.js.map +0 -1
- package/lib/server/public/AxioControl/.vite/manifest.json +0 -11
- package/lib/server/public/AxioControl/.vite/ssr-manifest.json +0 -813
- package/lib/server/public/AxioControl/assets/index-BRccHygR.js +0 -157
- package/lib/server/public/DONT_TOUCH_THIS_FILE.js.map +0 -1
- package/lib/server/router/Router.js.map +0 -1
- package/lib/server/router/Routers/Auth.routes.js.map +0 -1
- package/lib/server/router/Routers/Collection.routes.js.map +0 -1
- package/lib/server/router/Routers/DB.routes.js.map +0 -1
- package/lib/server/router/Routers/Index.routes.js.map +0 -1
- package/lib/server/router/Routers/Operation.routes.js.map +0 -1
- package/lib/server/router/Routers/RoleManagement.routes.js.map +0 -1
- package/lib/server/router/Routers/UserManagement.routes.js.map +0 -1
- package/lib/tcp/config/keys.js.map +0 -1
- package/lib/tcp/config/permissions.js.map +0 -1
- package/lib/tcp/config/protocol.js.map +0 -1
- package/lib/tcp/config/server.js.map +0 -1
- package/lib/tcp/connection/ConnectionManager.js.map +0 -1
- package/lib/tcp/connection/ConnectionRateLimiter.js.map +0 -1
- package/lib/tcp/connection/RequestContext.js.map +0 -1
- package/lib/tcp/connection/TransactionManager.js.map +0 -1
- package/lib/tcp/handler/CommandHandler.js.map +0 -1
- package/lib/tcp/handler/handlers/Auth.handler.js.map +0 -1
- package/lib/tcp/handler/handlers/Collection.handler.js.map +0 -1
- package/lib/tcp/handler/handlers/DB.handler.js.map +0 -1
- package/lib/tcp/handler/handlers/Operation.handler.js.map +0 -1
- package/lib/tcp/handler/handlers/Transaction.handler.js.map +0 -1
- package/lib/tcp/types/command.types.js.map +0 -1
- package/lib/tcp/types/protocol.types.js.map +0 -1
- package/lib/utility/BufferLoaderWithWorker.utils.js.map +0 -1
- package/lib/utility/Searcher.utils.js.map +0 -1
- package/lib/utility/SortData.utils.js.map +0 -1
- package/lib/utility/ZipUnzip.utils.js.map +0 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RegexGuard - Static ReDoS guard for user-supplied regex patterns.
|
|
3
|
+
*
|
|
4
|
+
* Rejects patterns that are too long, contain nested unbounded quantifiers
|
|
5
|
+
* (`(a+)+`), or have overlapping alternation branches inside an unboundedly
|
|
6
|
+
* quantified group (`(a|aa)+`). Bounded quantifiers like `{2,9}` are allowed.
|
|
7
|
+
*
|
|
8
|
+
* @class RegexGuard
|
|
9
|
+
* @example
|
|
10
|
+
* const safe = RegexGuard.compileRegex("(a+)b", "");
|
|
11
|
+
* const guarded = RegexGuard.compileRegex("(a+)+$", ""); // throws
|
|
12
|
+
*/
|
|
13
|
+
export default class RegexGuard {
|
|
14
|
+
/** Upper bound on pattern length. */
|
|
15
|
+
static readonly MAX_PATTERN_LENGTH = 512;
|
|
16
|
+
/**
|
|
17
|
+
* Compiles a user-supplied pattern into a RegExp after proving it is safe.
|
|
18
|
+
* @param pattern - The regex source to compile.
|
|
19
|
+
* @param flags - Optional regex flags (e.g. "i").
|
|
20
|
+
* @returns A compiled RegExp.
|
|
21
|
+
* @throws Error if the pattern is empty, too long, or prone to catastrophic backtracking.
|
|
22
|
+
*/
|
|
23
|
+
static compileRegex(pattern: string, flags?: string): RegExp;
|
|
24
|
+
/**
|
|
25
|
+
* Returns true when the pattern does not contain the catastrophic
|
|
26
|
+
* nested-quantifier shape. Pure check - callers decide what to do.
|
|
27
|
+
* @param pattern - The regex source to inspect.
|
|
28
|
+
* @returns true if the pattern is considered safe, false otherwise.
|
|
29
|
+
*/
|
|
30
|
+
static isSafePattern(pattern: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Static scan for the catastrophic-backtracking shape.
|
|
33
|
+
*
|
|
34
|
+
* Two classes are rejected:
|
|
35
|
+
* 1. Nested unbounded quantifiers: a group that contains an internally
|
|
36
|
+
* quantified atom and is itself unboundedly quantified, e.g. `(a+)+`.
|
|
37
|
+
* 2. Overlapping alternation inside an unboundedly quantified group: two
|
|
38
|
+
* branches where one is a strict prefix of another, e.g. `(a|aa)+` -
|
|
39
|
+
* the parser cannot decide where a branch ends, causing exponential work.
|
|
40
|
+
*
|
|
41
|
+
* @param pattern - The regex source to inspect.
|
|
42
|
+
* @throws Error describing the dangerous construct when detected.
|
|
43
|
+
*/
|
|
44
|
+
static assertSafePattern(pattern: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Splits a group body on top-level alternation operators and reports whether
|
|
47
|
+
* any two branches overlap, i.e. one is a strict prefix of another. Branch
|
|
48
|
+
* overlap on an unboundedly quantified group is what produces exponential
|
|
49
|
+
* backtracking in patterns like `(a|aa)+`.
|
|
50
|
+
* @param body - The characters between a group's '(' and ')'.
|
|
51
|
+
* @returns true when an overlapping branch pair is found.
|
|
52
|
+
*/
|
|
53
|
+
private static hasOverlappingAlternation;
|
|
54
|
+
/**
|
|
55
|
+
* Strips the special group marker (`?:`, `?=`, `?!`, `?<=`, `?<!`, `?<name>`)
|
|
56
|
+
* from a group body so branch analysis sees the actual alternation content.
|
|
57
|
+
* @param body - The raw text between '(' and ')'.
|
|
58
|
+
* @returns The body without its leading marker, if one was present.
|
|
59
|
+
*/
|
|
60
|
+
private static stripGroupMarker;
|
|
61
|
+
/**
|
|
62
|
+
* Splits a group body on '|' operators that are not nested inside a
|
|
63
|
+
* sub-group or character class.
|
|
64
|
+
* @param body - The group's raw body text.
|
|
65
|
+
* @returns The top-level alternation branches (at least one element).
|
|
66
|
+
*/
|
|
67
|
+
private static splitTopLevel;
|
|
68
|
+
/**
|
|
69
|
+
* Determines what kind of quantifier (if any) follows a closing parenthesis.
|
|
70
|
+
* @param pattern - The full regex source.
|
|
71
|
+
* @param closeIndex - Index of the ')' that just closed a group.
|
|
72
|
+
* @returns "none" when no quantifier follows, "unbounded" for `*`, `+`, or an
|
|
73
|
+
* open-ended `{n,}` range, otherwise "bounded".
|
|
74
|
+
*/
|
|
75
|
+
private static peekGroupQuantifier;
|
|
76
|
+
/**
|
|
77
|
+
* Parses a `{...}` quantifier starting at the given index.
|
|
78
|
+
* @param pattern - The full regex source.
|
|
79
|
+
* @param openIndex - Index of the '{'.
|
|
80
|
+
* @returns true for an unbounded `{n,}` range, false for a bounded `{n}` or
|
|
81
|
+
* `{n,m}`, and null when the character is not actually a quantifier
|
|
82
|
+
* (e.g. a literal brace inside a larger construct).
|
|
83
|
+
*/
|
|
84
|
+
private static isUnboundedRange;
|
|
85
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* RegexGuard - Static ReDoS guard for user-supplied regex patterns.
|
|
5
|
+
*
|
|
6
|
+
* Rejects patterns that are too long, contain nested unbounded quantifiers
|
|
7
|
+
* (`(a+)+`), or have overlapping alternation branches inside an unboundedly
|
|
8
|
+
* quantified group (`(a|aa)+`). Bounded quantifiers like `{2,9}` are allowed.
|
|
9
|
+
*
|
|
10
|
+
* @class RegexGuard
|
|
11
|
+
* @example
|
|
12
|
+
* const safe = RegexGuard.compileRegex("(a+)b", "");
|
|
13
|
+
* const guarded = RegexGuard.compileRegex("(a+)+$", ""); // throws
|
|
14
|
+
*/
|
|
15
|
+
class RegexGuard {
|
|
16
|
+
/**
|
|
17
|
+
* Compiles a user-supplied pattern into a RegExp after proving it is safe.
|
|
18
|
+
* @param pattern - The regex source to compile.
|
|
19
|
+
* @param flags - Optional regex flags (e.g. "i").
|
|
20
|
+
* @returns A compiled RegExp.
|
|
21
|
+
* @throws Error if the pattern is empty, too long, or prone to catastrophic backtracking.
|
|
22
|
+
*/
|
|
23
|
+
static compileRegex(pattern, flags) {
|
|
24
|
+
if (!pattern || typeof pattern !== "string") {
|
|
25
|
+
throw new Error("Invalid regex pattern: must be a non-empty string");
|
|
26
|
+
}
|
|
27
|
+
if (pattern.length > this.MAX_PATTERN_LENGTH) {
|
|
28
|
+
throw new Error(`Regex pattern exceeds maximum length of ${this.MAX_PATTERN_LENGTH}`);
|
|
29
|
+
}
|
|
30
|
+
this.assertSafePattern(pattern);
|
|
31
|
+
return new RegExp(pattern, flags || "");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Returns true when the pattern does not contain the catastrophic
|
|
35
|
+
* nested-quantifier shape. Pure check - callers decide what to do.
|
|
36
|
+
* @param pattern - The regex source to inspect.
|
|
37
|
+
* @returns true if the pattern is considered safe, false otherwise.
|
|
38
|
+
*/
|
|
39
|
+
static isSafePattern(pattern) {
|
|
40
|
+
try {
|
|
41
|
+
this.assertSafePattern(pattern);
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch (_a) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Static scan for the catastrophic-backtracking shape.
|
|
50
|
+
*
|
|
51
|
+
* Two classes are rejected:
|
|
52
|
+
* 1. Nested unbounded quantifiers: a group that contains an internally
|
|
53
|
+
* quantified atom and is itself unboundedly quantified, e.g. `(a+)+`.
|
|
54
|
+
* 2. Overlapping alternation inside an unboundedly quantified group: two
|
|
55
|
+
* branches where one is a strict prefix of another, e.g. `(a|aa)+` -
|
|
56
|
+
* the parser cannot decide where a branch ends, causing exponential work.
|
|
57
|
+
*
|
|
58
|
+
* @param pattern - The regex source to inspect.
|
|
59
|
+
* @throws Error describing the dangerous construct when detected.
|
|
60
|
+
*/
|
|
61
|
+
static assertSafePattern(pattern) {
|
|
62
|
+
let inClass = false;
|
|
63
|
+
let escaped = false;
|
|
64
|
+
// Stack of currently-open groups; each tracks whether it contains an
|
|
65
|
+
// internally quantified atom and where it opened (for branch analysis).
|
|
66
|
+
const groups = [];
|
|
67
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
68
|
+
const c = pattern[i];
|
|
69
|
+
if (escaped) {
|
|
70
|
+
escaped = false;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (c === "\\") {
|
|
74
|
+
escaped = true;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// Inside a character class like [abc+]: '+' is a literal there, not a quantifier.
|
|
78
|
+
if (inClass) {
|
|
79
|
+
if (c === "]")
|
|
80
|
+
inClass = false;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (c === "[") {
|
|
84
|
+
inClass = true;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (c === "(") {
|
|
88
|
+
groups.push({ openIndex: i, hasQuantifiedAtom: false });
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (c === ")") {
|
|
92
|
+
const group = groups.pop();
|
|
93
|
+
if (!group)
|
|
94
|
+
continue;
|
|
95
|
+
const quantifier = this.peekGroupQuantifier(pattern, i);
|
|
96
|
+
const isUnbounded = quantifier === "unbounded";
|
|
97
|
+
if (isUnbounded) {
|
|
98
|
+
if (group.hasQuantifiedAtom) {
|
|
99
|
+
throw new Error("Regex pattern rejected: contains nested quantifiers that can cause catastrophic backtracking");
|
|
100
|
+
}
|
|
101
|
+
const body = pattern.slice(group.openIndex + 1, i);
|
|
102
|
+
if (this.hasOverlappingAlternation(this.stripGroupMarker(body))) {
|
|
103
|
+
throw new Error("Regex pattern rejected: quantified alternation with overlapping branches can cause catastrophic backtracking");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// A quantified group, or a group containing quantified atoms, is itself
|
|
107
|
+
// a quantified atom to its parent group.
|
|
108
|
+
const isQuantifiedAtom = group.hasQuantifiedAtom || isUnbounded;
|
|
109
|
+
if (isQuantifiedAtom && groups.length > 0) {
|
|
110
|
+
groups[groups.length - 1].hasQuantifiedAtom = true;
|
|
111
|
+
}
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
// Track unbounded quantifiers (+ or * or {n,}): the atom before them is a
|
|
115
|
+
// quantified atom. '?' is deliberately excluded - a single optional atom
|
|
116
|
+
// cannot blow up on its own. `{m}` bounded and `{m,n}` bounded are also excluded.
|
|
117
|
+
let isUnbounded = false;
|
|
118
|
+
if (c === "+" || c === "*") {
|
|
119
|
+
isUnbounded = true;
|
|
120
|
+
}
|
|
121
|
+
else if (c === "{") {
|
|
122
|
+
isUnbounded = this.isUnboundedRange(pattern, i) === true;
|
|
123
|
+
}
|
|
124
|
+
if (isUnbounded && groups.length > 0) {
|
|
125
|
+
groups[groups.length - 1].hasQuantifiedAtom = true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Splits a group body on top-level alternation operators and reports whether
|
|
131
|
+
* any two branches overlap, i.e. one is a strict prefix of another. Branch
|
|
132
|
+
* overlap on an unboundedly quantified group is what produces exponential
|
|
133
|
+
* backtracking in patterns like `(a|aa)+`.
|
|
134
|
+
* @param body - The characters between a group's '(' and ')'.
|
|
135
|
+
* @returns true when an overlapping branch pair is found.
|
|
136
|
+
*/
|
|
137
|
+
static hasOverlappingAlternation(body) {
|
|
138
|
+
const branches = this.splitTopLevel(body);
|
|
139
|
+
if (branches.length < 2)
|
|
140
|
+
return false;
|
|
141
|
+
for (let i = 0; i < branches.length; i++) {
|
|
142
|
+
for (let j = 0; j < branches.length; j++) {
|
|
143
|
+
if (i === j)
|
|
144
|
+
continue;
|
|
145
|
+
const a = branches[i];
|
|
146
|
+
const b = branches[j];
|
|
147
|
+
// An empty branch can match zero width, so no line is consumed - the
|
|
148
|
+
// classic `(|x)+` / `(a|)+` ambiguity.
|
|
149
|
+
if (a === "" || b === "")
|
|
150
|
+
return true;
|
|
151
|
+
if (b.length > a.length && b.startsWith(a))
|
|
152
|
+
return true;
|
|
153
|
+
if (a.length > b.length && a.startsWith(b))
|
|
154
|
+
return true;
|
|
155
|
+
if (a === b)
|
|
156
|
+
return true; // duplicate branches are always ambiguous
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Strips the special group marker (`?:`, `?=`, `?!`, `?<=`, `?<!`, `?<name>`)
|
|
163
|
+
* from a group body so branch analysis sees the actual alternation content.
|
|
164
|
+
* @param body - The raw text between '(' and ')'.
|
|
165
|
+
* @returns The body without its leading marker, if one was present.
|
|
166
|
+
*/
|
|
167
|
+
static stripGroupMarker(body) {
|
|
168
|
+
if (body[0] === "?" && body[1] === "<") {
|
|
169
|
+
const close = body.indexOf(">");
|
|
170
|
+
return close >= 0 ? body.slice(close + 1) : body;
|
|
171
|
+
}
|
|
172
|
+
if (body[0] === "?" && (body[1] === ":" || body[1] === "=" || body[1] === "!")) {
|
|
173
|
+
return body.slice(2);
|
|
174
|
+
}
|
|
175
|
+
return body;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Splits a group body on '|' operators that are not nested inside a
|
|
179
|
+
* sub-group or character class.
|
|
180
|
+
* @param body - The group's raw body text.
|
|
181
|
+
* @returns The top-level alternation branches (at least one element).
|
|
182
|
+
*/
|
|
183
|
+
static splitTopLevel(body) {
|
|
184
|
+
const branches = [];
|
|
185
|
+
let depth = 0;
|
|
186
|
+
let inClass = false;
|
|
187
|
+
let escaped = false;
|
|
188
|
+
let current = "";
|
|
189
|
+
for (const c of body) {
|
|
190
|
+
if (escaped) {
|
|
191
|
+
escaped = false;
|
|
192
|
+
current += c;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (c === "\\") {
|
|
196
|
+
escaped = true;
|
|
197
|
+
current += c;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (inClass) {
|
|
201
|
+
current += c;
|
|
202
|
+
if (c === "]")
|
|
203
|
+
inClass = false;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (c === "[") {
|
|
207
|
+
inClass = true;
|
|
208
|
+
current += c;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (c === "(") {
|
|
212
|
+
depth++;
|
|
213
|
+
current += c;
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (c === ")") {
|
|
217
|
+
depth--;
|
|
218
|
+
current += c;
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
if (c === "|" && depth === 0) {
|
|
222
|
+
branches.push(current);
|
|
223
|
+
current = "";
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
current += c;
|
|
227
|
+
}
|
|
228
|
+
branches.push(current);
|
|
229
|
+
return branches;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Determines what kind of quantifier (if any) follows a closing parenthesis.
|
|
233
|
+
* @param pattern - The full regex source.
|
|
234
|
+
* @param closeIndex - Index of the ')' that just closed a group.
|
|
235
|
+
* @returns "none" when no quantifier follows, "unbounded" for `*`, `+`, or an
|
|
236
|
+
* open-ended `{n,}` range, otherwise "bounded".
|
|
237
|
+
*/
|
|
238
|
+
static peekGroupQuantifier(pattern, closeIndex) {
|
|
239
|
+
const next = pattern[closeIndex + 1];
|
|
240
|
+
if (next === "*" || next === "+")
|
|
241
|
+
return "unbounded";
|
|
242
|
+
if (next === "{") {
|
|
243
|
+
const bounded = this.isUnboundedRange(pattern, closeIndex + 1);
|
|
244
|
+
return bounded === true ? "unbounded" : bounded === false ? "bounded" : "none";
|
|
245
|
+
}
|
|
246
|
+
if (next === "?")
|
|
247
|
+
return "bounded";
|
|
248
|
+
return "none";
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Parses a `{...}` quantifier starting at the given index.
|
|
252
|
+
* @param pattern - The full regex source.
|
|
253
|
+
* @param openIndex - Index of the '{'.
|
|
254
|
+
* @returns true for an unbounded `{n,}` range, false for a bounded `{n}` or
|
|
255
|
+
* `{n,m}`, and null when the character is not actually a quantifier
|
|
256
|
+
* (e.g. a literal brace inside a larger construct).
|
|
257
|
+
*/
|
|
258
|
+
static isUnboundedRange(pattern, openIndex) {
|
|
259
|
+
let closeIndex = openIndex + 1;
|
|
260
|
+
while (closeIndex < pattern.length && pattern[closeIndex] !== "}") {
|
|
261
|
+
closeIndex++;
|
|
262
|
+
}
|
|
263
|
+
if (closeIndex >= pattern.length)
|
|
264
|
+
return null;
|
|
265
|
+
const body = pattern.slice(openIndex + 1, closeIndex);
|
|
266
|
+
if (/^\d+$/.test(body))
|
|
267
|
+
return false;
|
|
268
|
+
if (/^\d+,\d+$/.test(body))
|
|
269
|
+
return false;
|
|
270
|
+
if (/^\d+,$/.test(body))
|
|
271
|
+
return true;
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/** Upper bound on pattern length. */
|
|
276
|
+
RegexGuard.MAX_PATTERN_LENGTH = 512;
|
|
277
|
+
exports.default = RegexGuard;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SafeErrorMessage - Redacts filesystem paths and internal details from error
|
|
3
|
+
* messages before they are returned to remote clients.
|
|
4
|
+
* @class SafeErrorMessage
|
|
5
|
+
* @example
|
|
6
|
+
* SafeErrorMessage.sanitize(new Error("open '/home/user/db'"));
|
|
7
|
+
* // 'open <path>'
|
|
8
|
+
*/
|
|
9
|
+
export default class SafeErrorMessage {
|
|
10
|
+
static readonly MAX_MESSAGE_LENGTH = 300;
|
|
11
|
+
static readonly FALLBACK_MESSAGE = "An internal error occurred. Please try again later.";
|
|
12
|
+
/**
|
|
13
|
+
* Sanitizes an error for transmission to a remote client.
|
|
14
|
+
* @param error - The caught error (may be any unknown).
|
|
15
|
+
* @returns A single-line, path-redacted message with a bounded length.
|
|
16
|
+
*/
|
|
17
|
+
static sanitize(error: unknown): string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* SafeErrorMessage - Redacts filesystem paths and internal details from error
|
|
5
|
+
* messages before they are returned to remote clients.
|
|
6
|
+
* @class SafeErrorMessage
|
|
7
|
+
* @example
|
|
8
|
+
* SafeErrorMessage.sanitize(new Error("open '/home/user/db'"));
|
|
9
|
+
* // 'open <path>'
|
|
10
|
+
*/
|
|
11
|
+
class SafeErrorMessage {
|
|
12
|
+
/**
|
|
13
|
+
* Sanitizes an error for transmission to a remote client.
|
|
14
|
+
* @param error - The caught error (may be any unknown).
|
|
15
|
+
* @returns A single-line, path-redacted message with a bounded length.
|
|
16
|
+
*/
|
|
17
|
+
static sanitize(error) {
|
|
18
|
+
const raw = error instanceof Error
|
|
19
|
+
? error.message
|
|
20
|
+
: typeof error === "string"
|
|
21
|
+
? error
|
|
22
|
+
: error !== undefined
|
|
23
|
+
? String(error)
|
|
24
|
+
: "";
|
|
25
|
+
let message = raw;
|
|
26
|
+
message = message.replace(/[a-zA-Z]:\\[^\s"'`]+/g, "<path>");
|
|
27
|
+
message = message.replace(/(^|[\s(['"`])[\/][^\s"'`]+/g, "$1<path>");
|
|
28
|
+
message = message.replace(/(^|[\s(['"`])(?:\.\.?(?:[\/\\]|$))[^\s"'`]*/g, "$1<path>");
|
|
29
|
+
message = message.replace(/['"`]\s*<path>\s*['"`]/g, "<path>");
|
|
30
|
+
message = message.replace(/\r?\n/g, " | ").replace(/\s{2,}/g, " ").trim();
|
|
31
|
+
if (!message || message === "<path>")
|
|
32
|
+
return this.FALLBACK_MESSAGE;
|
|
33
|
+
if (message.length > this.MAX_MESSAGE_LENGTH) {
|
|
34
|
+
message = message.slice(0, this.MAX_MESSAGE_LENGTH - 3) + "...";
|
|
35
|
+
}
|
|
36
|
+
return message;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
SafeErrorMessage.MAX_MESSAGE_LENGTH = 300;
|
|
40
|
+
SafeErrorMessage.FALLBACK_MESSAGE = "An internal error occurred. Please try again later.";
|
|
41
|
+
exports.default = SafeErrorMessage;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.getNestedValue = getNestedValue;
|
|
4
7
|
exports.setNestedValue = setNestedValue;
|
|
5
8
|
exports.evaluateExpression = evaluateExpression;
|
|
9
|
+
const RegexGuard_helper_1 = __importDefault(require("../../../Helper/RegexGuard.helper"));
|
|
6
10
|
function getNestedValue(obj, path) {
|
|
7
11
|
if (!path || !obj)
|
|
8
12
|
return undefined;
|
|
@@ -153,7 +157,7 @@ function evaluateExpression(doc, expr) {
|
|
|
153
157
|
case "$regexMatch": {
|
|
154
158
|
const input = exprObj.$regexMatch;
|
|
155
159
|
const str = String(evaluateExpression(doc, input.input));
|
|
156
|
-
const regex =
|
|
160
|
+
const regex = RegexGuard_helper_1.default.compileRegex(input.regex, input.options || "");
|
|
157
161
|
return regex.test(str);
|
|
158
162
|
}
|
|
159
163
|
case "$cmp": {
|
|
@@ -587,4 +591,3 @@ function convertType(value, to) {
|
|
|
587
591
|
default: return value;
|
|
588
592
|
}
|
|
589
593
|
}
|
|
590
|
-
//# sourceMappingURL=expressionOperators.js.map
|
|
@@ -8,6 +8,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.BUILT_IN_STAGE_OPERATORS = void 0;
|
|
13
16
|
exports.executeMatch = executeMatch;
|
|
@@ -32,6 +35,7 @@ exports.executeMergeObjects = executeMergeObjects;
|
|
|
32
35
|
const expressionOperators_1 = require("./expressionOperators");
|
|
33
36
|
const accumulatorOperators_1 = require("./accumulatorOperators");
|
|
34
37
|
const OperatorRegistry_1 = require("../OperatorRegistry");
|
|
38
|
+
const RegexGuard_helper_1 = __importDefault(require("../../../Helper/RegexGuard.helper"));
|
|
35
39
|
function matchesCondition(itemValue, condition) {
|
|
36
40
|
if (condition === null || condition === undefined) {
|
|
37
41
|
return itemValue === null || itemValue === undefined;
|
|
@@ -44,7 +48,7 @@ function matchesCondition(itemValue, condition) {
|
|
|
44
48
|
if (typeof condition === "object") {
|
|
45
49
|
if ("$regex" in condition) {
|
|
46
50
|
try {
|
|
47
|
-
return
|
|
51
|
+
return RegexGuard_helper_1.default.compileRegex(String(condition.$regex), condition.$options || "").test(String(itemValue));
|
|
48
52
|
}
|
|
49
53
|
catch (_a) {
|
|
50
54
|
return false;
|
|
@@ -561,4 +565,3 @@ exports.BUILT_IN_STAGE_OPERATORS = {
|
|
|
561
565
|
$replaceRoot: executeReplaceRoot,
|
|
562
566
|
$replaceWith: executeReplaceRoot,
|
|
563
567
|
};
|
|
564
|
-
//# sourceMappingURL=stageOperators.js.map
|