vikunja-mcp-ng 0.4.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/LICENSE +21 -0
- package/README.md +123 -0
- package/dist/auth/AuthManager.d.ts +63 -0
- package/dist/auth/AuthManager.d.ts.map +1 -0
- package/dist/auth/AuthManager.js +137 -0
- package/dist/auth/AuthManager.js.map +1 -0
- package/dist/auth/index.d.ts +7 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +14 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/permissions.d.ts +60 -0
- package/dist/auth/permissions.d.ts.map +1 -0
- package/dist/auth/permissions.js +173 -0
- package/dist/auth/permissions.js.map +1 -0
- package/dist/client/VikunjaClientFactory.d.ts +41 -0
- package/dist/client/VikunjaClientFactory.d.ts.map +1 -0
- package/dist/client/VikunjaClientFactory.js +58 -0
- package/dist/client/VikunjaClientFactory.js.map +1 -0
- package/dist/client.d.ts +70 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +136 -0
- package/dist/client.js.map +1 -0
- package/dist/config/ConfigurationManager.d.ts +106 -0
- package/dist/config/ConfigurationManager.d.ts.map +1 -0
- package/dist/config/ConfigurationManager.js +509 -0
- package/dist/config/ConfigurationManager.js.map +1 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +36 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/secrets.d.ts +33 -0
- package/dist/config/secrets.d.ts.map +1 -0
- package/dist/config/secrets.js +90 -0
- package/dist/config/secrets.js.map +1 -0
- package/dist/config/types.d.ts +1113 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +189 -0
- package/dist/config/types.js.map +1 -0
- package/dist/formatters/BatchImportResponseFormatter.d.ts +89 -0
- package/dist/formatters/BatchImportResponseFormatter.d.ts.map +1 -0
- package/dist/formatters/BatchImportResponseFormatter.js +125 -0
- package/dist/formatters/BatchImportResponseFormatter.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +130 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/direct-middleware.d.ts +9 -0
- package/dist/middleware/direct-middleware.d.ts.map +1 -0
- package/dist/middleware/direct-middleware.js +49 -0
- package/dist/middleware/direct-middleware.js.map +1 -0
- package/dist/middleware/index.d.ts +8 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +21 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/simplified-rate-limit.d.ts +147 -0
- package/dist/middleware/simplified-rate-limit.d.ts.map +1 -0
- package/dist/middleware/simplified-rate-limit.js +533 -0
- package/dist/middleware/simplified-rate-limit.js.map +1 -0
- package/dist/parsers/CSVParser.d.ts +36 -0
- package/dist/parsers/CSVParser.d.ts.map +1 -0
- package/dist/parsers/CSVParser.js +69 -0
- package/dist/parsers/CSVParser.js.map +1 -0
- package/dist/parsers/InputParserFactory.d.ts +17 -0
- package/dist/parsers/InputParserFactory.d.ts.map +1 -0
- package/dist/parsers/InputParserFactory.js +137 -0
- package/dist/parsers/InputParserFactory.js.map +1 -0
- package/dist/parsers/JSONParser.d.ts +74 -0
- package/dist/parsers/JSONParser.d.ts.map +1 -0
- package/dist/parsers/JSONParser.js +69 -0
- package/dist/parsers/JSONParser.js.map +1 -0
- package/dist/services/EntityResolver.d.ts +92 -0
- package/dist/services/EntityResolver.d.ts.map +1 -0
- package/dist/services/EntityResolver.js +201 -0
- package/dist/services/EntityResolver.js.map +1 -0
- package/dist/services/TaskCreationService.d.ts +99 -0
- package/dist/services/TaskCreationService.d.ts.map +1 -0
- package/dist/services/TaskCreationService.js +392 -0
- package/dist/services/TaskCreationService.js.map +1 -0
- package/dist/storage/SimpleFilterStorage.d.ts +103 -0
- package/dist/storage/SimpleFilterStorage.d.ts.map +1 -0
- package/dist/storage/SimpleFilterStorage.js +350 -0
- package/dist/storage/SimpleFilterStorage.js.map +1 -0
- package/dist/storage/filtering/FilterSerializer.d.ts +45 -0
- package/dist/storage/filtering/FilterSerializer.d.ts.map +1 -0
- package/dist/storage/filtering/FilterSerializer.js +171 -0
- package/dist/storage/filtering/FilterSerializer.js.map +1 -0
- package/dist/storage/filtering/FilterValidator.d.ts +59 -0
- package/dist/storage/filtering/FilterValidator.d.ts.map +1 -0
- package/dist/storage/filtering/FilterValidator.js +183 -0
- package/dist/storage/filtering/FilterValidator.js.map +1 -0
- package/dist/storage/index.d.ts +61 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +125 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/templateFileStore.d.ts +62 -0
- package/dist/storage/templateFileStore.d.ts.map +1 -0
- package/dist/storage/templateFileStore.js +151 -0
- package/dist/storage/templateFileStore.js.map +1 -0
- package/dist/tools/admin.d.ts +51 -0
- package/dist/tools/admin.d.ts.map +1 -0
- package/dist/tools/admin.js +207 -0
- package/dist/tools/admin.js.map +1 -0
- package/dist/tools/auth.d.ts +9 -0
- package/dist/tools/auth.d.ts.map +1 -0
- package/dist/tools/auth.js +175 -0
- package/dist/tools/auth.js.map +1 -0
- package/dist/tools/batch-import.d.ts +5 -0
- package/dist/tools/batch-import.d.ts.map +1 -0
- package/dist/tools/batch-import.js +153 -0
- package/dist/tools/batch-import.js.map +1 -0
- package/dist/tools/caldav-tokens.d.ts +45 -0
- package/dist/tools/caldav-tokens.d.ts.map +1 -0
- package/dist/tools/caldav-tokens.js +93 -0
- package/dist/tools/caldav-tokens.js.map +1 -0
- package/dist/tools/export.d.ts +14 -0
- package/dist/tools/export.d.ts.map +1 -0
- package/dist/tools/export.js +252 -0
- package/dist/tools/export.js.map +1 -0
- package/dist/tools/filters.d.ts +50 -0
- package/dist/tools/filters.d.ts.map +1 -0
- package/dist/tools/filters.js +512 -0
- package/dist/tools/filters.js.map +1 -0
- package/dist/tools/index.d.ts +53 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +217 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/labels.d.ts +22 -0
- package/dist/tools/labels.d.ts.map +1 -0
- package/dist/tools/labels.js +206 -0
- package/dist/tools/labels.js.map +1 -0
- package/dist/tools/notifications.d.ts +17 -0
- package/dist/tools/notifications.d.ts.map +1 -0
- package/dist/tools/notifications.js +171 -0
- package/dist/tools/notifications.js.map +1 -0
- package/dist/tools/projects/backgrounds.d.ts +80 -0
- package/dist/tools/projects/backgrounds.d.ts.map +1 -0
- package/dist/tools/projects/backgrounds.js +154 -0
- package/dist/tools/projects/backgrounds.js.map +1 -0
- package/dist/tools/projects/buckets.d.ts +147 -0
- package/dist/tools/projects/buckets.d.ts.map +1 -0
- package/dist/tools/projects/buckets.js +291 -0
- package/dist/tools/projects/buckets.js.map +1 -0
- package/dist/tools/projects/crud.d.ts +145 -0
- package/dist/tools/projects/crud.d.ts.map +1 -0
- package/dist/tools/projects/crud.js +425 -0
- package/dist/tools/projects/crud.js.map +1 -0
- package/dist/tools/projects/duplicate.d.ts +41 -0
- package/dist/tools/projects/duplicate.d.ts.map +1 -0
- package/dist/tools/projects/duplicate.js +49 -0
- package/dist/tools/projects/duplicate.js.map +1 -0
- package/dist/tools/projects/hierarchy.d.ts +77 -0
- package/dist/tools/projects/hierarchy.d.ts.map +1 -0
- package/dist/tools/projects/hierarchy.js +300 -0
- package/dist/tools/projects/hierarchy.js.map +1 -0
- package/dist/tools/projects/index.d.ts +34 -0
- package/dist/tools/projects/index.d.ts.map +1 -0
- package/dist/tools/projects/index.js +522 -0
- package/dist/tools/projects/index.js.map +1 -0
- package/dist/tools/projects/permission.d.ts +26 -0
- package/dist/tools/projects/permission.d.ts.map +1 -0
- package/dist/tools/projects/permission.js +53 -0
- package/dist/tools/projects/permission.js.map +1 -0
- package/dist/tools/projects/response-formatter.d.ts +54 -0
- package/dist/tools/projects/response-formatter.d.ts.map +1 -0
- package/dist/tools/projects/response-formatter.js +139 -0
- package/dist/tools/projects/response-formatter.js.map +1 -0
- package/dist/tools/projects/sharing-access.d.ts +165 -0
- package/dist/tools/projects/sharing-access.d.ts.map +1 -0
- package/dist/tools/projects/sharing-access.js +450 -0
- package/dist/tools/projects/sharing-access.js.map +1 -0
- package/dist/tools/projects/sharing.d.ts +105 -0
- package/dist/tools/projects/sharing.d.ts.map +1 -0
- package/dist/tools/projects/sharing.js +258 -0
- package/dist/tools/projects/sharing.js.map +1 -0
- package/dist/tools/projects/validation.d.ts +51 -0
- package/dist/tools/projects/validation.d.ts.map +1 -0
- package/dist/tools/projects/validation.js +160 -0
- package/dist/tools/projects/validation.js.map +1 -0
- package/dist/tools/projects/views.d.ts +161 -0
- package/dist/tools/projects/views.d.ts.map +1 -0
- package/dist/tools/projects/views.js +234 -0
- package/dist/tools/projects/views.js.map +1 -0
- package/dist/tools/projects.d.ts +20 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +66 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/reactions.d.ts +25 -0
- package/dist/tools/reactions.d.ts.map +1 -0
- package/dist/tools/reactions.js +108 -0
- package/dist/tools/reactions.js.map +1 -0
- package/dist/tools/subscriptions.d.ts +23 -0
- package/dist/tools/subscriptions.d.ts.map +1 -0
- package/dist/tools/subscriptions.js +111 -0
- package/dist/tools/subscriptions.js.map +1 -0
- package/dist/tools/task-assignees.d.ts +13 -0
- package/dist/tools/task-assignees.d.ts.map +1 -0
- package/dist/tools/task-assignees.js +74 -0
- package/dist/tools/task-assignees.js.map +1 -0
- package/dist/tools/task-bulk.d.ts +13 -0
- package/dist/tools/task-bulk.d.ts.map +1 -0
- package/dist/tools/task-bulk.js +117 -0
- package/dist/tools/task-bulk.js.map +1 -0
- package/dist/tools/task-comments.d.ts +12 -0
- package/dist/tools/task-comments.d.ts.map +1 -0
- package/dist/tools/task-comments.js +65 -0
- package/dist/tools/task-comments.js.map +1 -0
- package/dist/tools/task-crud.d.ts +13 -0
- package/dist/tools/task-crud.d.ts.map +1 -0
- package/dist/tools/task-crud.js +168 -0
- package/dist/tools/task-crud.js.map +1 -0
- package/dist/tools/task-labels.d.ts +13 -0
- package/dist/tools/task-labels.d.ts.map +1 -0
- package/dist/tools/task-labels.js +64 -0
- package/dist/tools/task-labels.js.map +1 -0
- package/dist/tools/task-relations.d.ts +13 -0
- package/dist/tools/task-relations.d.ts.map +1 -0
- package/dist/tools/task-relations.js +74 -0
- package/dist/tools/task-relations.js.map +1 -0
- package/dist/tools/task-reminders.d.ts +13 -0
- package/dist/tools/task-reminders.d.ts.map +1 -0
- package/dist/tools/task-reminders.js +69 -0
- package/dist/tools/task-reminders.js.map +1 -0
- package/dist/tools/tasks/assignees/AssigneeOperationsService.d.ts +63 -0
- package/dist/tools/tasks/assignees/AssigneeOperationsService.d.ts.map +1 -0
- package/dist/tools/tasks/assignees/AssigneeOperationsService.js +152 -0
- package/dist/tools/tasks/assignees/AssigneeOperationsService.js.map +1 -0
- package/dist/tools/tasks/assignees/AssigneeResponseFormatter.d.ts +28 -0
- package/dist/tools/tasks/assignees/AssigneeResponseFormatter.d.ts.map +1 -0
- package/dist/tools/tasks/assignees/AssigneeResponseFormatter.js +73 -0
- package/dist/tools/tasks/assignees/AssigneeResponseFormatter.js.map +1 -0
- package/dist/tools/tasks/assignees/AssigneeValidationService.d.ts +46 -0
- package/dist/tools/tasks/assignees/AssigneeValidationService.d.ts.map +1 -0
- package/dist/tools/tasks/assignees/AssigneeValidationService.js +70 -0
- package/dist/tools/tasks/assignees/AssigneeValidationService.js.map +1 -0
- package/dist/tools/tasks/assignees/index.d.ts +52 -0
- package/dist/tools/tasks/assignees/index.d.ts.map +1 -0
- package/dist/tools/tasks/assignees/index.js +103 -0
- package/dist/tools/tasks/assignees/index.js.map +1 -0
- package/dist/tools/tasks/attach.d.ts +39 -0
- package/dist/tools/tasks/attach.d.ts.map +1 -0
- package/dist/tools/tasks/attach.js +90 -0
- package/dist/tools/tasks/attach.js.map +1 -0
- package/dist/tools/tasks/attachments.d.ts +67 -0
- package/dist/tools/tasks/attachments.d.ts.map +1 -0
- package/dist/tools/tasks/attachments.js +153 -0
- package/dist/tools/tasks/attachments.js.map +1 -0
- package/dist/tools/tasks/buckets.d.ts +41 -0
- package/dist/tools/tasks/buckets.d.ts.map +1 -0
- package/dist/tools/tasks/buckets.js +75 -0
- package/dist/tools/tasks/buckets.js.map +1 -0
- package/dist/tools/tasks/bulk/BatchProcessorFactory.d.ts +30 -0
- package/dist/tools/tasks/bulk/BatchProcessorFactory.d.ts.map +1 -0
- package/dist/tools/tasks/bulk/BatchProcessorFactory.js +69 -0
- package/dist/tools/tasks/bulk/BatchProcessorFactory.js.map +1 -0
- package/dist/tools/tasks/bulk/BulkOperationErrorHandler.d.ts +50 -0
- package/dist/tools/tasks/bulk/BulkOperationErrorHandler.d.ts.map +1 -0
- package/dist/tools/tasks/bulk/BulkOperationErrorHandler.js +183 -0
- package/dist/tools/tasks/bulk/BulkOperationErrorHandler.js.map +1 -0
- package/dist/tools/tasks/bulk/BulkOperationProcessor.d.ts +101 -0
- package/dist/tools/tasks/bulk/BulkOperationProcessor.d.ts.map +1 -0
- package/dist/tools/tasks/bulk/BulkOperationProcessor.js +416 -0
- package/dist/tools/tasks/bulk/BulkOperationProcessor.js.map +1 -0
- package/dist/tools/tasks/bulk/BulkOperationTypes.d.ts +50 -0
- package/dist/tools/tasks/bulk/BulkOperationTypes.d.ts.map +1 -0
- package/dist/tools/tasks/bulk/BulkOperationTypes.js +6 -0
- package/dist/tools/tasks/bulk/BulkOperationTypes.js.map +1 -0
- package/dist/tools/tasks/bulk/BulkOperationValidator.d.ts +53 -0
- package/dist/tools/tasks/bulk/BulkOperationValidator.d.ts.map +1 -0
- package/dist/tools/tasks/bulk/BulkOperationValidator.js +216 -0
- package/dist/tools/tasks/bulk/BulkOperationValidator.js.map +1 -0
- package/dist/tools/tasks/bulk/index.d.ts +9 -0
- package/dist/tools/tasks/bulk/index.d.ts.map +1 -0
- package/dist/tools/tasks/bulk/index.js +15 -0
- package/dist/tools/tasks/bulk/index.js.map +1 -0
- package/dist/tools/tasks/bulk-operations-simplified.d.ts +62 -0
- package/dist/tools/tasks/bulk-operations-simplified.d.ts.map +1 -0
- package/dist/tools/tasks/bulk-operations-simplified.js +416 -0
- package/dist/tools/tasks/bulk-operations-simplified.js.map +1 -0
- package/dist/tools/tasks/bulk-operations.d.ts +8 -0
- package/dist/tools/tasks/bulk-operations.d.ts.map +1 -0
- package/dist/tools/tasks/bulk-operations.js +13 -0
- package/dist/tools/tasks/bulk-operations.js.map +1 -0
- package/dist/tools/tasks/by-index.d.ts +36 -0
- package/dist/tools/tasks/by-index.d.ts.map +1 -0
- package/dist/tools/tasks/by-index.js +52 -0
- package/dist/tools/tasks/by-index.js.map +1 -0
- package/dist/tools/tasks/comments/CommentOperationsService.d.ts +44 -0
- package/dist/tools/tasks/comments/CommentOperationsService.d.ts.map +1 -0
- package/dist/tools/tasks/comments/CommentOperationsService.js +86 -0
- package/dist/tools/tasks/comments/CommentOperationsService.js.map +1 -0
- package/dist/tools/tasks/comments/CommentResponseFormatter.d.ts +41 -0
- package/dist/tools/tasks/comments/CommentResponseFormatter.d.ts.map +1 -0
- package/dist/tools/tasks/comments/CommentResponseFormatter.js +114 -0
- package/dist/tools/tasks/comments/CommentResponseFormatter.js.map +1 -0
- package/dist/tools/tasks/comments/CommentValidationService.d.ts +62 -0
- package/dist/tools/tasks/comments/CommentValidationService.d.ts.map +1 -0
- package/dist/tools/tasks/comments/CommentValidationService.js +105 -0
- package/dist/tools/tasks/comments/CommentValidationService.js.map +1 -0
- package/dist/tools/tasks/comments/index.d.ts +66 -0
- package/dist/tools/tasks/comments/index.d.ts.map +1 -0
- package/dist/tools/tasks/comments/index.js +99 -0
- package/dist/tools/tasks/comments/index.js.map +1 -0
- package/dist/tools/tasks/constants.d.ts +19 -0
- package/dist/tools/tasks/constants.d.ts.map +1 -0
- package/dist/tools/tasks/constants.js +82 -0
- package/dist/tools/tasks/constants.js.map +1 -0
- package/dist/tools/tasks/crud/TaskCreationService.d.ts +29 -0
- package/dist/tools/tasks/crud/TaskCreationService.d.ts.map +1 -0
- package/dist/tools/tasks/crud/TaskCreationService.js +274 -0
- package/dist/tools/tasks/crud/TaskCreationService.js.map +1 -0
- package/dist/tools/tasks/crud/TaskDeletionService.d.ts +19 -0
- package/dist/tools/tasks/crud/TaskDeletionService.d.ts.map +1 -0
- package/dist/tools/tasks/crud/TaskDeletionService.js +96 -0
- package/dist/tools/tasks/crud/TaskDeletionService.js.map +1 -0
- package/dist/tools/tasks/crud/TaskReadService.d.ts +19 -0
- package/dist/tools/tasks/crud/TaskReadService.d.ts.map +1 -0
- package/dist/tools/tasks/crud/TaskReadService.js +66 -0
- package/dist/tools/tasks/crud/TaskReadService.js.map +1 -0
- package/dist/tools/tasks/crud/TaskResponseFormatter.d.ts +18 -0
- package/dist/tools/tasks/crud/TaskResponseFormatter.d.ts.map +1 -0
- package/dist/tools/tasks/crud/TaskResponseFormatter.js +248 -0
- package/dist/tools/tasks/crud/TaskResponseFormatter.js.map +1 -0
- package/dist/tools/tasks/crud/TaskUpdateService.d.ts +33 -0
- package/dist/tools/tasks/crud/TaskUpdateService.d.ts.map +1 -0
- package/dist/tools/tasks/crud/TaskUpdateService.js +294 -0
- package/dist/tools/tasks/crud/TaskUpdateService.js.map +1 -0
- package/dist/tools/tasks/crud/index.d.ts +17 -0
- package/dist/tools/tasks/crud/index.d.ts.map +1 -0
- package/dist/tools/tasks/crud/index.js +20 -0
- package/dist/tools/tasks/crud/index.js.map +1 -0
- package/dist/tools/tasks/duplicate.d.ts +28 -0
- package/dist/tools/tasks/duplicate.d.ts.map +1 -0
- package/dist/tools/tasks/duplicate.js +41 -0
- package/dist/tools/tasks/duplicate.js.map +1 -0
- package/dist/tools/tasks/filtering/FilterExecutor.d.ts +39 -0
- package/dist/tools/tasks/filtering/FilterExecutor.d.ts.map +1 -0
- package/dist/tools/tasks/filtering/FilterExecutor.js +214 -0
- package/dist/tools/tasks/filtering/FilterExecutor.js.map +1 -0
- package/dist/tools/tasks/filtering/FilterValidator.d.ts +59 -0
- package/dist/tools/tasks/filtering/FilterValidator.d.ts.map +1 -0
- package/dist/tools/tasks/filtering/FilterValidator.js +257 -0
- package/dist/tools/tasks/filtering/FilterValidator.js.map +1 -0
- package/dist/tools/tasks/filtering/TaskFilteringOrchestrator.d.ts +78 -0
- package/dist/tools/tasks/filtering/TaskFilteringOrchestrator.d.ts.map +1 -0
- package/dist/tools/tasks/filtering/TaskFilteringOrchestrator.js +195 -0
- package/dist/tools/tasks/filtering/TaskFilteringOrchestrator.js.map +1 -0
- package/dist/tools/tasks/filtering/evaluators.d.ts +41 -0
- package/dist/tools/tasks/filtering/evaluators.d.ts.map +1 -0
- package/dist/tools/tasks/filtering/evaluators.js +224 -0
- package/dist/tools/tasks/filtering/evaluators.js.map +1 -0
- package/dist/tools/tasks/filtering/index.d.ts +11 -0
- package/dist/tools/tasks/filtering/index.d.ts.map +1 -0
- package/dist/tools/tasks/filtering/index.js +26 -0
- package/dist/tools/tasks/filtering/index.js.map +1 -0
- package/dist/tools/tasks/index.d.ts +9 -0
- package/dist/tools/tasks/index.d.ts.map +1 -0
- package/dist/tools/tasks/index.js +337 -0
- package/dist/tools/tasks/index.js.map +1 -0
- package/dist/tools/tasks/labels.d.ts +49 -0
- package/dist/tools/tasks/labels.d.ts.map +1 -0
- package/dist/tools/tasks/labels.js +223 -0
- package/dist/tools/tasks/labels.js.map +1 -0
- package/dist/tools/tasks/mark-read.d.ts +27 -0
- package/dist/tools/tasks/mark-read.d.ts.map +1 -0
- package/dist/tools/tasks/mark-read.js +38 -0
- package/dist/tools/tasks/mark-read.js.map +1 -0
- package/dist/tools/tasks/position.d.ts +53 -0
- package/dist/tools/tasks/position.d.ts.map +1 -0
- package/dist/tools/tasks/position.js +83 -0
- package/dist/tools/tasks/position.js.map +1 -0
- package/dist/tools/tasks/reminders.d.ts +56 -0
- package/dist/tools/tasks/reminders.d.ts.map +1 -0
- package/dist/tools/tasks/reminders.js +213 -0
- package/dist/tools/tasks/reminders.js.map +1 -0
- package/dist/tools/tasks/subtasks.d.ts +85 -0
- package/dist/tools/tasks/subtasks.d.ts.map +1 -0
- package/dist/tools/tasks/subtasks.js +286 -0
- package/dist/tools/tasks/subtasks.js.map +1 -0
- package/dist/tools/tasks/types/filters.d.ts +136 -0
- package/dist/tools/tasks/types/filters.d.ts.map +1 -0
- package/dist/tools/tasks/types/filters.js +7 -0
- package/dist/tools/tasks/types/filters.js.map +1 -0
- package/dist/tools/tasks/validation.d.ts +47 -0
- package/dist/tools/tasks/validation.d.ts.map +1 -0
- package/dist/tools/tasks/validation.js +131 -0
- package/dist/tools/tasks/validation.js.map +1 -0
- package/dist/tools/tasks-relations.d.ts +25 -0
- package/dist/tools/tasks-relations.d.ts.map +1 -0
- package/dist/tools/tasks-relations.js +271 -0
- package/dist/tools/tasks-relations.js.map +1 -0
- package/dist/tools/tasks.d.ts +6 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +10 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/tools/teams.d.ts +9 -0
- package/dist/tools/teams.d.ts.map +1 -0
- package/dist/tools/teams.js +255 -0
- package/dist/tools/teams.js.map +1 -0
- package/dist/tools/templates.d.ts +9 -0
- package/dist/tools/templates.d.ts.map +1 -0
- package/dist/tools/templates.js +450 -0
- package/dist/tools/templates.js.map +1 -0
- package/dist/tools/tokens.d.ts +37 -0
- package/dist/tools/tokens.d.ts.map +1 -0
- package/dist/tools/tokens.js +122 -0
- package/dist/tools/tokens.js.map +1 -0
- package/dist/tools/user-deletion.d.ts +41 -0
- package/dist/tools/user-deletion.d.ts.map +1 -0
- package/dist/tools/user-deletion.js +126 -0
- package/dist/tools/user-deletion.js.map +1 -0
- package/dist/tools/users.d.ts +9 -0
- package/dist/tools/users.d.ts.map +1 -0
- package/dist/tools/users.js +418 -0
- package/dist/tools/users.js.map +1 -0
- package/dist/tools/webhooks.d.ts +31 -0
- package/dist/tools/webhooks.d.ts.map +1 -0
- package/dist/tools/webhooks.js +414 -0
- package/dist/tools/webhooks.js.map +1 -0
- package/dist/transforms/base.d.ts +204 -0
- package/dist/transforms/base.d.ts.map +1 -0
- package/dist/transforms/base.js +175 -0
- package/dist/transforms/base.js.map +1 -0
- package/dist/transforms/field-selector.d.ts +27 -0
- package/dist/transforms/field-selector.d.ts.map +1 -0
- package/dist/transforms/field-selector.js +91 -0
- package/dist/transforms/field-selector.js.map +1 -0
- package/dist/transforms/index.d.ts +15 -0
- package/dist/transforms/index.d.ts.map +1 -0
- package/dist/transforms/index.js +50 -0
- package/dist/transforms/index.js.map +1 -0
- package/dist/transforms/size-calculator.d.ts +131 -0
- package/dist/transforms/size-calculator.d.ts.map +1 -0
- package/dist/transforms/size-calculator.js +284 -0
- package/dist/transforms/size-calculator.js.map +1 -0
- package/dist/transforms/task.d.ts +207 -0
- package/dist/transforms/task.d.ts.map +1 -0
- package/dist/transforms/task.js +259 -0
- package/dist/transforms/task.js.map +1 -0
- package/dist/types/errors.d.ts +65 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +44 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/filters.d.ts +149 -0
- package/dist/types/filters.d.ts.map +1 -0
- package/dist/types/filters.js +26 -0
- package/dist/types/filters.js.map +1 -0
- package/dist/types/index.d.ts +147 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +24 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/node-vikunja-extended.d.ts +36 -0
- package/dist/types/node-vikunja-extended.d.ts.map +1 -0
- package/dist/types/node-vikunja-extended.js +25 -0
- package/dist/types/node-vikunja-extended.js.map +1 -0
- package/dist/types/responses.d.ts +121 -0
- package/dist/types/responses.d.ts.map +1 -0
- package/dist/types/responses.js +26 -0
- package/dist/types/responses.js.map +1 -0
- package/dist/types/vikunja.d.ts +319 -0
- package/dist/types/vikunja.d.ts.map +1 -0
- package/dist/types/vikunja.js +7 -0
- package/dist/types/vikunja.js.map +1 -0
- package/dist/utils/auth-error-handler.d.ts +23 -0
- package/dist/utils/auth-error-handler.d.ts.map +1 -0
- package/dist/utils/auth-error-handler.js +162 -0
- package/dist/utils/auth-error-handler.js.map +1 -0
- package/dist/utils/composite-operation.d.ts +184 -0
- package/dist/utils/composite-operation.d.ts.map +1 -0
- package/dist/utils/composite-operation.js +293 -0
- package/dist/utils/composite-operation.js.map +1 -0
- package/dist/utils/error-handler.d.ts +39 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +336 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/filtering/ClientSideFilteringStrategy.d.ts +13 -0
- package/dist/utils/filtering/ClientSideFilteringStrategy.d.ts.map +1 -0
- package/dist/utils/filtering/ClientSideFilteringStrategy.js +129 -0
- package/dist/utils/filtering/ClientSideFilteringStrategy.js.map +1 -0
- package/dist/utils/filtering/FilteringContext.d.ts +40 -0
- package/dist/utils/filtering/FilteringContext.d.ts.map +1 -0
- package/dist/utils/filtering/FilteringContext.js +58 -0
- package/dist/utils/filtering/FilteringContext.js.map +1 -0
- package/dist/utils/filtering/HybridFilteringStrategy.d.ts +15 -0
- package/dist/utils/filtering/HybridFilteringStrategy.d.ts.map +1 -0
- package/dist/utils/filtering/HybridFilteringStrategy.js +55 -0
- package/dist/utils/filtering/HybridFilteringStrategy.js.map +1 -0
- package/dist/utils/filtering/RestCrossProjectFilteringStrategy.d.ts +42 -0
- package/dist/utils/filtering/RestCrossProjectFilteringStrategy.d.ts.map +1 -0
- package/dist/utils/filtering/RestCrossProjectFilteringStrategy.js +120 -0
- package/dist/utils/filtering/RestCrossProjectFilteringStrategy.js.map +1 -0
- package/dist/utils/filtering/ServerSideFilteringStrategy.d.ts +13 -0
- package/dist/utils/filtering/ServerSideFilteringStrategy.d.ts.map +1 -0
- package/dist/utils/filtering/ServerSideFilteringStrategy.js +88 -0
- package/dist/utils/filtering/ServerSideFilteringStrategy.js.map +1 -0
- package/dist/utils/filtering/TaskFilteringStrategy.d.ts +19 -0
- package/dist/utils/filtering/TaskFilteringStrategy.d.ts.map +1 -0
- package/dist/utils/filtering/TaskFilteringStrategy.js +10 -0
- package/dist/utils/filtering/TaskFilteringStrategy.js.map +1 -0
- package/dist/utils/filtering/index.d.ts +14 -0
- package/dist/utils/filtering/index.d.ts.map +1 -0
- package/dist/utils/filtering/index.js +22 -0
- package/dist/utils/filtering/index.js.map +1 -0
- package/dist/utils/filtering/types.d.ts +108 -0
- package/dist/utils/filtering/types.d.ts.map +1 -0
- package/dist/utils/filtering/types.js +6 -0
- package/dist/utils/filtering/types.js.map +1 -0
- package/dist/utils/filters.d.ts +70 -0
- package/dist/utils/filters.d.ts.map +1 -0
- package/dist/utils/filters.js +812 -0
- package/dist/utils/filters.js.map +1 -0
- package/dist/utils/http-error-detail.d.ts +28 -0
- package/dist/utils/http-error-detail.d.ts.map +1 -0
- package/dist/utils/http-error-detail.js +67 -0
- package/dist/utils/http-error-detail.js.map +1 -0
- package/dist/utils/label-bulk.d.ts +21 -0
- package/dist/utils/label-bulk.d.ts.map +1 -0
- package/dist/utils/label-bulk.js +51 -0
- package/dist/utils/label-bulk.js.map +1 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +66 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/memory.d.ts +73 -0
- package/dist/utils/memory.d.ts.map +1 -0
- package/dist/utils/memory.js +194 -0
- package/dist/utils/memory.js.map +1 -0
- package/dist/utils/performance/batch-processor.d.ts +77 -0
- package/dist/utils/performance/batch-processor.d.ts.map +1 -0
- package/dist/utils/performance/batch-processor.js +218 -0
- package/dist/utils/performance/batch-processor.js.map +1 -0
- package/dist/utils/performance/index.d.ts +42 -0
- package/dist/utils/performance/index.d.ts.map +1 -0
- package/dist/utils/performance/index.js +49 -0
- package/dist/utils/performance/index.js.map +1 -0
- package/dist/utils/performance/performance-monitor.d.ts +116 -0
- package/dist/utils/performance/performance-monitor.d.ts.map +1 -0
- package/dist/utils/performance/performance-monitor.js +307 -0
- package/dist/utils/performance/performance-monitor.js.map +1 -0
- package/dist/utils/read-only.d.ts +111 -0
- package/dist/utils/read-only.d.ts.map +1 -0
- package/dist/utils/read-only.js +503 -0
- package/dist/utils/read-only.js.map +1 -0
- package/dist/utils/response-factory.d.ts +81 -0
- package/dist/utils/response-factory.d.ts.map +1 -0
- package/dist/utils/response-factory.js +86 -0
- package/dist/utils/response-factory.js.map +1 -0
- package/dist/utils/retry.d.ts +160 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +316 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/security.d.ts +70 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +358 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/simple-response.d.ts +75 -0
- package/dist/utils/simple-response.d.ts.map +1 -0
- package/dist/utils/simple-response.js +311 -0
- package/dist/utils/simple-response.js.map +1 -0
- package/dist/utils/storage-errors.d.ts +9 -0
- package/dist/utils/storage-errors.d.ts.map +1 -0
- package/dist/utils/storage-errors.js +20 -0
- package/dist/utils/storage-errors.js.map +1 -0
- package/dist/utils/task-rest-transport.d.ts +28 -0
- package/dist/utils/task-rest-transport.d.ts.map +1 -0
- package/dist/utils/task-rest-transport.js +33 -0
- package/dist/utils/task-rest-transport.js.map +1 -0
- package/dist/utils/unicode-fix.d.ts +19 -0
- package/dist/utils/unicode-fix.d.ts.map +1 -0
- package/dist/utils/unicode-fix.js +70 -0
- package/dist/utils/unicode-fix.js.map +1 -0
- package/dist/utils/validation.d.ts +75 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +758 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/utils/vikunja-rest.d.ts +159 -0
- package/dist/utils/vikunja-rest.d.ts.map +1 -0
- package/dist/utils/vikunja-rest.js +378 -0
- package/dist/utils/vikunja-rest.js.map +1 -0
- package/docs/CONFIGURATION.md +957 -0
- package/docs/DOCKER-DESKTOP-MCP.md +207 -0
- package/docs/TOOLS.md +422 -0
- package/package.json +145 -0
|
@@ -0,0 +1,758 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Comprehensive Input Sanitization and Security Validation Layer
|
|
4
|
+
*
|
|
5
|
+
* Provides enterprise-grade protection against:
|
|
6
|
+
* - XSS attacks (script injection, HTML injection)
|
|
7
|
+
* - SQL injection (UNION, boolean-based, time-based)
|
|
8
|
+
* - Command injection (shell command execution)
|
|
9
|
+
* - Path traversal attacks
|
|
10
|
+
* - LDAP injection
|
|
11
|
+
* - NoSQL injection
|
|
12
|
+
* - Unicode and encoding bypasses
|
|
13
|
+
* - Content Security Policy violations
|
|
14
|
+
*
|
|
15
|
+
* Integration: Works seamlessly with existing security.ts credential masking
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.sanitizeString = sanitizeString;
|
|
19
|
+
exports.validateField = validateField;
|
|
20
|
+
exports.validateOperator = validateOperator;
|
|
21
|
+
exports.validateLogicalOperator = validateLogicalOperator;
|
|
22
|
+
exports.validateValue = validateValue;
|
|
23
|
+
exports.validateCondition = validateCondition;
|
|
24
|
+
exports.validateFilterExpression = validateFilterExpression;
|
|
25
|
+
exports.safeJsonStringify = safeJsonStringify;
|
|
26
|
+
exports.safeJsonParse = safeJsonParse;
|
|
27
|
+
exports.validateId = validateId;
|
|
28
|
+
exports.validateAndConvertId = validateAndConvertId;
|
|
29
|
+
const zod_1 = require("zod");
|
|
30
|
+
const errors_1 = require("../types/errors");
|
|
31
|
+
/**
|
|
32
|
+
* Maximum allowed nesting depth for filter expressions (prevents DoS)
|
|
33
|
+
*/
|
|
34
|
+
const MAX_NESTING_DEPTH = 10;
|
|
35
|
+
/**
|
|
36
|
+
* Maximum allowed number of conditions per expression (prevents DoS)
|
|
37
|
+
*/
|
|
38
|
+
const MAX_CONDITIONS = 50;
|
|
39
|
+
/**
|
|
40
|
+
* Maximum string length for filter values (prevents storage bloat)
|
|
41
|
+
*/
|
|
42
|
+
const MAX_STRING_LENGTH = 1000;
|
|
43
|
+
/**
|
|
44
|
+
* Zod schemas for type-safe validation
|
|
45
|
+
*/
|
|
46
|
+
const FieldSchema = zod_1.z.enum([
|
|
47
|
+
'done', 'priority', 'percentDone', 'dueDate', 'startDate', 'endDate',
|
|
48
|
+
'doneAt', 'project', 'assignees',
|
|
49
|
+
'labels', 'created', 'updated', 'title', 'description'
|
|
50
|
+
]);
|
|
51
|
+
const OperatorSchema = zod_1.z.enum([
|
|
52
|
+
'=', '!=', '>', '>=', '<', '<=', 'like', 'in', 'not in'
|
|
53
|
+
]);
|
|
54
|
+
const LogicalOperatorSchema = zod_1.z.enum(['&&', '||']);
|
|
55
|
+
/**
|
|
56
|
+
* Server-appropriate security validation patterns
|
|
57
|
+
* Created fresh each call to avoid regex state issues
|
|
58
|
+
*/
|
|
59
|
+
/**
|
|
60
|
+
* Allowed characters for additional strictness (optional, can be relaxed)
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* Validate and sanitize a string value to prevent XSS using pattern matching + HTML escaping
|
|
64
|
+
* Server-appropriate approach that avoids DOM parsing while providing comprehensive protection
|
|
65
|
+
*/
|
|
66
|
+
function sanitizeString(value) {
|
|
67
|
+
if (typeof value !== 'string') {
|
|
68
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Value must be a string');
|
|
69
|
+
}
|
|
70
|
+
if (value.length > MAX_STRING_LENGTH) {
|
|
71
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `String value exceeds maximum length of ${MAX_STRING_LENGTH}`);
|
|
72
|
+
}
|
|
73
|
+
// Step 1: Check for dangerous HTML/JavaScript patterns and REJECT them (don't sanitize)
|
|
74
|
+
// Convert to lowercase for case-insensitive pattern matching
|
|
75
|
+
const lowerValue = value.toLowerCase();
|
|
76
|
+
// Create fresh patterns each time to avoid regex state issues
|
|
77
|
+
const dangerousPatterns = [
|
|
78
|
+
// Enhanced XSS patterns - comprehensive script and injection detection
|
|
79
|
+
/<script[^>]*>/gi,
|
|
80
|
+
/<\/script>/gi,
|
|
81
|
+
/<iframe[^>]*>/gi,
|
|
82
|
+
/<\/iframe>/gi,
|
|
83
|
+
/<object[^>]*>/gi,
|
|
84
|
+
/<\/object>/gi,
|
|
85
|
+
/<embed[^>]*>/gi,
|
|
86
|
+
/<link[^>]*>/gi,
|
|
87
|
+
/<meta[^>]*>/gi,
|
|
88
|
+
/<svg[^>]*>/gi,
|
|
89
|
+
/<\/svg>/gi,
|
|
90
|
+
/<style[^>]*>/gi,
|
|
91
|
+
/<\/style>/gi,
|
|
92
|
+
/<img[^>]*on[^>]*>/gi,
|
|
93
|
+
/<div[^>]*on[^>]*>/gi,
|
|
94
|
+
/<a[^>]*on[^>]*>/gi,
|
|
95
|
+
/<body[^>]*on[^>]*>/gi,
|
|
96
|
+
/<form[^>]*on[^>]*>/gi,
|
|
97
|
+
/<input[^>]*on[^>]*>/gi,
|
|
98
|
+
/<button[^>]*on[^>]*>/gi,
|
|
99
|
+
/<select[^>]*on[^>]*>/gi,
|
|
100
|
+
/<textarea[^>]*on[^>]*>/gi,
|
|
101
|
+
// Event handlers with attributes (more specific to avoid false positives)
|
|
102
|
+
/on\w+\s*=\s*["'][^"']*["']/gi,
|
|
103
|
+
/onclick/gi,
|
|
104
|
+
/onload/gi,
|
|
105
|
+
/onerror/gi,
|
|
106
|
+
/onmouseover/gi,
|
|
107
|
+
/onmouseout/gi,
|
|
108
|
+
/onmousedown/gi,
|
|
109
|
+
/onmouseup/gi,
|
|
110
|
+
/onkeydown/gi,
|
|
111
|
+
/onkeyup/gi,
|
|
112
|
+
/onkeypress/gi,
|
|
113
|
+
/onfocus/gi,
|
|
114
|
+
/onblur/gi,
|
|
115
|
+
/onchange/gi,
|
|
116
|
+
/onsubmit/gi,
|
|
117
|
+
/onreset/gi,
|
|
118
|
+
/onselect/gi,
|
|
119
|
+
/onunload/gi,
|
|
120
|
+
/onabort/gi,
|
|
121
|
+
/oncanplay/gi,
|
|
122
|
+
/oncanplaythrough/gi,
|
|
123
|
+
/oncuechange/gi,
|
|
124
|
+
/ondurationchange/gi,
|
|
125
|
+
/onemptied/gi,
|
|
126
|
+
/onended/gi,
|
|
127
|
+
/onerror/gi,
|
|
128
|
+
/onloadeddata/gi,
|
|
129
|
+
/onloadedmetadata/gi,
|
|
130
|
+
/onloadstart/gi,
|
|
131
|
+
/onpause/gi,
|
|
132
|
+
/onplay/gi,
|
|
133
|
+
/onplaying/gi,
|
|
134
|
+
/onprogress/gi,
|
|
135
|
+
/onratechange/gi,
|
|
136
|
+
/onseeked/gi,
|
|
137
|
+
/onseeking/gi,
|
|
138
|
+
/onstalled/gi,
|
|
139
|
+
/onsuspend/gi,
|
|
140
|
+
/ontimeupdate/gi,
|
|
141
|
+
/onvolumechange/gi,
|
|
142
|
+
/onwaiting/gi,
|
|
143
|
+
// Dangerous protocols and schemes
|
|
144
|
+
/javascript:/gi,
|
|
145
|
+
/vbscript:/gi,
|
|
146
|
+
/data:text\/html/gi,
|
|
147
|
+
/data:application\/javascript/gi,
|
|
148
|
+
/data:text\/javascript/gi,
|
|
149
|
+
/data:text\/vbscript/gi,
|
|
150
|
+
/data:application\/x-javascript/gi,
|
|
151
|
+
// CSS-based attacks
|
|
152
|
+
/expression\s*\(/gi,
|
|
153
|
+
/@import/gi,
|
|
154
|
+
/url\s*\(/gi,
|
|
155
|
+
/binding\s*:/gi,
|
|
156
|
+
/behavior\s*:/gi,
|
|
157
|
+
/-moz-binding\s*:/gi,
|
|
158
|
+
/-o-link\s*:/gi,
|
|
159
|
+
/-webkit-binding\s*:/gi,
|
|
160
|
+
// SQL injection patterns (narrow: only flag time-delay/blind injection, not plain English words)
|
|
161
|
+
/(\b(WAITFOR\s+DELAY|SLEEP\s*\(|BENCHMARK\s*\(|DBMS_PIPE\.RECEIVE_MESSAGE)\b)/gi,
|
|
162
|
+
/(\b(XP_|SP_)\w+)/gi, // SQL Server extended procedures
|
|
163
|
+
// Boolean-based blind SQL injection (e.g. `' OR '1'='1`). Requires a quote immediately
|
|
164
|
+
// after OR/AND plus an `=` comparison, so it doesn't false-positive on ordinary English
|
|
165
|
+
// like "Fix bug or issue" or "Cost or budget = 500" (no quote follows OR/AND there).
|
|
166
|
+
/(\b(OR|AND)\b\s*["'][^"']*["']?\s*=\s*["']?[^"']*["']?)/gi,
|
|
167
|
+
// HTML comments (XSS vector regardless of context)
|
|
168
|
+
/<!--/gi,
|
|
169
|
+
// Command injection patterns (more specific to avoid false positives)
|
|
170
|
+
// The broad shell-metacharacter blocklist (`;&|`$(){}[]\'"*?<>~`) was removed because it
|
|
171
|
+
// rejected any string containing a bare quote or angle bracket. Generic, non-scripting
|
|
172
|
+
// HTML-like text (e.g. `<div class="x">`) is passed through unmodified: this boundary is a
|
|
173
|
+
// JSON API call, not an HTML render, so there is nothing to escape (see f2b0b93, which
|
|
174
|
+
// removed render-time HTML-escaping here for the same reason). Only constructs with actual
|
|
175
|
+
// scripting/DOM-execution vectors (script/iframe/style/svg tags, event handlers, dangerous
|
|
176
|
+
// protocols, etc.) are rejected above.
|
|
177
|
+
/(\b(wget|curl|nc|netcat|telnet|ssh|ftp|sftp)\b)/gi,
|
|
178
|
+
/(rm\s+-rf|del\s+\/s|format|fdisk|mkfs)/gi,
|
|
179
|
+
/(>\s*\/dev\/null|2>&1|\|\|)/gi,
|
|
180
|
+
/(\$\([^)]*\)|`[^`]*`)/gi, // Command substitution
|
|
181
|
+
// Path traversal patterns
|
|
182
|
+
/(\.\.[/\\])/gi,
|
|
183
|
+
/(%2e%2e[/\\])/gi,
|
|
184
|
+
/(%2e%2e%2f)/gi, // URL-encoded ../
|
|
185
|
+
/(%2e%2e%5c)/gi, // URL-encoded ..\
|
|
186
|
+
/(\/etc\/passwd|\/etc\/shadow|\/proc\/)/gi,
|
|
187
|
+
/(c:\\\\windows\\\\system32|\\\\..\\\\)/gi,
|
|
188
|
+
// LDAP injection patterns
|
|
189
|
+
/(\*\)\([&*)]*)/gi,
|
|
190
|
+
/(\*\)([^)]*\*)*)/gi,
|
|
191
|
+
/(\|\()([^)]*)(\)\|)/gi,
|
|
192
|
+
/(!\()([^)]*)(\))/gi,
|
|
193
|
+
// NoSQL injection patterns. The optional `["']?` before the colon covers both the raw
|
|
194
|
+
// `$gt:` form and the quoted-JSON-key form (`"$gt":`) produced by e.g. JSON.stringify.
|
|
195
|
+
/(\$\w+\s*["']?\s*:)/gi, // MongoDB operators like $gt, $lt, $where
|
|
196
|
+
/(\{\s*["']?\$where\s*["']?\s*:)/gi,
|
|
197
|
+
/(\{\s*["']?\$ne\s*["']?\s*:)/gi,
|
|
198
|
+
/(\{\s*["']?\$gt\s*["']?\s*:)/gi,
|
|
199
|
+
/(\{\s*["']?\$regex\s*["']?\s*:)/gi,
|
|
200
|
+
// HTML5 dangerous attributes
|
|
201
|
+
/formaction\s*=/gi,
|
|
202
|
+
/poster\s*=/gi,
|
|
203
|
+
/autofocus\s*=/gi,
|
|
204
|
+
/controls\s*=/gi,
|
|
205
|
+
/autoplay\s*=/gi,
|
|
206
|
+
/loop\s*=/gi,
|
|
207
|
+
/muted\s*=/gi,
|
|
208
|
+
// Unicode and encoding bypass attempts
|
|
209
|
+
/[\u200b-\u200f\u2060\u180e\ufeff]/g, // Zero-width and invisible characters
|
|
210
|
+
/[\uFE00-\uFE0F]/g, // Variation selectors
|
|
211
|
+
/\\u[0-9a-fA-F]{4}/g, // Unicode escapes
|
|
212
|
+
/\\x[0-9a-fA-F]{2}/g, // Hex escapes
|
|
213
|
+
// Prototype pollution patterns
|
|
214
|
+
/(__proto__|constructor|prototype)/gi,
|
|
215
|
+
// Content Security Policy violations
|
|
216
|
+
/(base64|atob|btoa|eval|Function|setTimeout|setInterval)\s*\(/gi,
|
|
217
|
+
/(document\.(write|writeln|open|close)|window\.(open|location|navigate))/gi,
|
|
218
|
+
// HTML-encoded dangerous content (prevent XSS through encoded vectors)
|
|
219
|
+
/<script[^&]*>/gi,
|
|
220
|
+
/<\/script>/gi,
|
|
221
|
+
/<iframe[^&]*>/gi,
|
|
222
|
+
/<\/iframe>/gi,
|
|
223
|
+
/<object[^&]*>/gi,
|
|
224
|
+
/<svg[^&]*>/gi,
|
|
225
|
+
/<img[^&]*on[^&]*>/gi,
|
|
226
|
+
/<div[^&]*on[^&]*>/gi,
|
|
227
|
+
/<a[^&]*on[^&]*>/gi,
|
|
228
|
+
/<body[^&]*on[^&]*>/gi,
|
|
229
|
+
/<style[^&]*>/gi,
|
|
230
|
+
/<form[^&]*on[^&]*>/gi,
|
|
231
|
+
/javascript:[^&]*/gi,
|
|
232
|
+
/on\w+[^&]*=/gi,
|
|
233
|
+
/<!--.*?-->/gis, // HTML-encoded comments
|
|
234
|
+
];
|
|
235
|
+
for (const pattern of dangerousPatterns) {
|
|
236
|
+
// Reset regex lastIndex to avoid state issues with global flags
|
|
237
|
+
pattern.lastIndex = 0;
|
|
238
|
+
if (pattern.test(lowerValue)) {
|
|
239
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'String contains potentially dangerous content');
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Step 2: Apply comprehensive sanitization for safe content
|
|
243
|
+
// First, normalize Unicode to prevent bypass attacks
|
|
244
|
+
let normalizedValue = value.normalize('NFC');
|
|
245
|
+
// Remove dangerous Unicode characters that weren't caught by pattern matching
|
|
246
|
+
normalizedValue = normalizedValue.replace(/[\u200b-\u200f\u2060\u180e\ufeff]/g, '');
|
|
247
|
+
normalizedValue = normalizedValue.replace(/[\uFE00-\uFE0F]/g, '');
|
|
248
|
+
// Apply path traversal sanitization for file system safety
|
|
249
|
+
normalizedValue = normalizedValue.replace(/\.\.[/\\]/g, '...');
|
|
250
|
+
normalizedValue = normalizedValue.replace(/%2e%2e[/\\]/gi, '...');
|
|
251
|
+
normalizedValue = normalizedValue.replace(/\/etc\/passwd/gi, 'etc/passwd');
|
|
252
|
+
normalizedValue = normalizedValue.replace(/c:\\windows\\system32/gi, 'c:/windows/system32');
|
|
253
|
+
return normalizedValue;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Validate a field name against Zod schema
|
|
257
|
+
*/
|
|
258
|
+
function validateField(field) {
|
|
259
|
+
if (typeof field !== 'string') {
|
|
260
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Field must be a string');
|
|
261
|
+
}
|
|
262
|
+
// Check for prototype pollution attempts first
|
|
263
|
+
const pollutionPatterns = ['__proto__', 'constructor', 'prototype', '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__'];
|
|
264
|
+
if (pollutionPatterns.includes(field)) {
|
|
265
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Invalid field name: potential prototype pollution');
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const result = FieldSchema.parse(field);
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
273
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Invalid field: ${error.issues[0]?.message || 'Unknown validation error'}`);
|
|
274
|
+
}
|
|
275
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Invalid field: Validation failed');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Validate an operator against Zod schema
|
|
280
|
+
*/
|
|
281
|
+
function validateOperator(operator) {
|
|
282
|
+
if (typeof operator !== 'string') {
|
|
283
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Operator must be a string');
|
|
284
|
+
}
|
|
285
|
+
try {
|
|
286
|
+
const result = OperatorSchema.parse(operator);
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
291
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Invalid operator: ${error.issues[0]?.message || 'Unknown validation error'}`);
|
|
292
|
+
}
|
|
293
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Invalid operator: Validation failed');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Validate a logical operator against Zod schema
|
|
298
|
+
*/
|
|
299
|
+
function validateLogicalOperator(operator) {
|
|
300
|
+
if (typeof operator !== 'string') {
|
|
301
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Logical operator must be a string');
|
|
302
|
+
}
|
|
303
|
+
try {
|
|
304
|
+
const result = LogicalOperatorSchema.parse(operator);
|
|
305
|
+
return result;
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
309
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Invalid logical operator: ${error.issues[0]?.message || 'Unknown validation error'}`);
|
|
310
|
+
}
|
|
311
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Invalid logical operator: Validation failed');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Validate and normalize a value using custom logic (more comprehensive than Zod for this use case)
|
|
316
|
+
*/
|
|
317
|
+
function validateValue(value) {
|
|
318
|
+
// Handle null/undefined
|
|
319
|
+
if (value === null || value === undefined) {
|
|
320
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Invalid value type');
|
|
321
|
+
}
|
|
322
|
+
// Handle string values
|
|
323
|
+
if (typeof value === 'string') {
|
|
324
|
+
return value;
|
|
325
|
+
}
|
|
326
|
+
// Handle boolean values
|
|
327
|
+
if (typeof value === 'boolean') {
|
|
328
|
+
return value;
|
|
329
|
+
}
|
|
330
|
+
// Handle number values with infinite/NaN checks
|
|
331
|
+
if (typeof value === 'number') {
|
|
332
|
+
if (!Number.isFinite(value)) {
|
|
333
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Numeric values must be finite, not infinite or NaN');
|
|
334
|
+
}
|
|
335
|
+
return value;
|
|
336
|
+
}
|
|
337
|
+
// Handle array values
|
|
338
|
+
if (Array.isArray(value)) {
|
|
339
|
+
if (value.length > 100) {
|
|
340
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Array values cannot exceed 100 elements');
|
|
341
|
+
}
|
|
342
|
+
if (value.length === 0) {
|
|
343
|
+
return [];
|
|
344
|
+
}
|
|
345
|
+
// Check array type consistency with proper type guards
|
|
346
|
+
const firstElementType = typeof value[0];
|
|
347
|
+
if (firstElementType !== 'string' && firstElementType !== 'number') {
|
|
348
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Array elements must be all strings or all finite numbers, not mixed');
|
|
349
|
+
}
|
|
350
|
+
// Validate all elements are of the same type and valid
|
|
351
|
+
for (let i = 0; i < value.length; i++) {
|
|
352
|
+
const element = value[i];
|
|
353
|
+
const elementType = typeof element;
|
|
354
|
+
// Additional safety: reject null/undefined/object elements
|
|
355
|
+
if (element === null || element === undefined || typeof element === 'object') {
|
|
356
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Array elements must be strings, numbers, or booleans, not objects');
|
|
357
|
+
}
|
|
358
|
+
if (elementType !== firstElementType) {
|
|
359
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Array elements must be all strings or all finite numbers, not mixed');
|
|
360
|
+
}
|
|
361
|
+
if (firstElementType === 'number') {
|
|
362
|
+
// Type-safe numeric validation without casting
|
|
363
|
+
if (typeof element !== 'number' || !Number.isFinite(element)) {
|
|
364
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Array numeric values must be finite, not infinite or NaN');
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if (firstElementType === 'string') {
|
|
368
|
+
// Type-safe string validation with comprehensive sanitization
|
|
369
|
+
if (typeof element !== 'string') {
|
|
370
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Array string elements must be strings');
|
|
371
|
+
}
|
|
372
|
+
// Apply comprehensive input sanitization to all string array elements
|
|
373
|
+
// This prevents injection attacks in bulk operations
|
|
374
|
+
try {
|
|
375
|
+
value[i] = sanitizeString(element);
|
|
376
|
+
}
|
|
377
|
+
catch (sanitizationError) {
|
|
378
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Array element ${i} contains potentially dangerous content: ${sanitizationError instanceof Error ? sanitizationError.message : 'Unknown error'}`);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// Type-safe return without unsafe casting - we've validated the types above
|
|
383
|
+
if (firstElementType === 'string') {
|
|
384
|
+
// We've proven all elements are strings
|
|
385
|
+
return value;
|
|
386
|
+
}
|
|
387
|
+
else if (firstElementType === 'number') {
|
|
388
|
+
// We've proven all elements are finite numbers
|
|
389
|
+
return value;
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
// This should never happen due to earlier validation
|
|
393
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Array contains unsupported element types');
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// Reject all other types
|
|
397
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Invalid value type');
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Schema for filter conditions
|
|
401
|
+
*/
|
|
402
|
+
const ConditionSchema = zod_1.z.object({
|
|
403
|
+
field: FieldSchema,
|
|
404
|
+
operator: OperatorSchema,
|
|
405
|
+
value: zod_1.z.union([
|
|
406
|
+
zod_1.z.string(),
|
|
407
|
+
zod_1.z.number(),
|
|
408
|
+
zod_1.z.boolean(),
|
|
409
|
+
zod_1.z.array(zod_1.z.string()),
|
|
410
|
+
zod_1.z.array(zod_1.z.number()),
|
|
411
|
+
zod_1.z.null()
|
|
412
|
+
]),
|
|
413
|
+
});
|
|
414
|
+
/**
|
|
415
|
+
* Validate a filter condition object using Zod schema
|
|
416
|
+
*/
|
|
417
|
+
function validateCondition(condition) {
|
|
418
|
+
try {
|
|
419
|
+
const result = ConditionSchema.parse(condition);
|
|
420
|
+
return result;
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
424
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Invalid condition: ${error.issues[0]?.message || 'Condition validation failed'}`);
|
|
425
|
+
}
|
|
426
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Invalid condition: Validation failed');
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Zod schema for filter groups
|
|
431
|
+
*/
|
|
432
|
+
const FilterGroupSchema = zod_1.z.object({
|
|
433
|
+
operator: LogicalOperatorSchema,
|
|
434
|
+
conditions: zod_1.z.array(ConditionSchema).min(1).max(MAX_CONDITIONS)
|
|
435
|
+
});
|
|
436
|
+
/**
|
|
437
|
+
* Zod schema for filter expressions
|
|
438
|
+
*/
|
|
439
|
+
const FilterExpressionSchema = zod_1.z.object({
|
|
440
|
+
groups: zod_1.z.array(FilterGroupSchema).min(1).max(MAX_NESTING_DEPTH),
|
|
441
|
+
operator: LogicalOperatorSchema.optional()
|
|
442
|
+
}).refine((expr) => {
|
|
443
|
+
// Check total conditions across all groups
|
|
444
|
+
const totalConditions = expr.groups.reduce((sum, group) => sum + group.conditions.length, 0);
|
|
445
|
+
return totalConditions <= MAX_CONDITIONS;
|
|
446
|
+
}, {
|
|
447
|
+
message: `Filter expression cannot exceed ${MAX_CONDITIONS} total conditions`
|
|
448
|
+
});
|
|
449
|
+
/**
|
|
450
|
+
* Validate a filter expression using Zod schema with comprehensive type safety
|
|
451
|
+
*/
|
|
452
|
+
function validateFilterExpression(expression) {
|
|
453
|
+
try {
|
|
454
|
+
// Use Zod for comprehensive type-safe validation
|
|
455
|
+
const result = FilterExpressionSchema.parse(expression);
|
|
456
|
+
// Additional runtime checks for edge cases Zod might not catch
|
|
457
|
+
if (result.groups.length === 0) {
|
|
458
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Filter expression must have at least one group');
|
|
459
|
+
}
|
|
460
|
+
// Validate each condition individually for additional safety
|
|
461
|
+
let totalConditions = 0;
|
|
462
|
+
for (let i = 0; i < result.groups.length; i++) {
|
|
463
|
+
const group = result.groups[i];
|
|
464
|
+
// Type guard to ensure group is defined
|
|
465
|
+
if (!group) {
|
|
466
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Group ${i} is undefined`);
|
|
467
|
+
}
|
|
468
|
+
// Validate operator with stricter validation
|
|
469
|
+
try {
|
|
470
|
+
validateLogicalOperator(group.operator);
|
|
471
|
+
}
|
|
472
|
+
catch (error) {
|
|
473
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Group ${i} has invalid operator: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
474
|
+
}
|
|
475
|
+
// Validate each condition individually
|
|
476
|
+
for (let j = 0; j < group.conditions.length; j++) {
|
|
477
|
+
const condition = group.conditions[j];
|
|
478
|
+
try {
|
|
479
|
+
validateCondition(condition);
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Group ${i}, condition ${j}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
483
|
+
}
|
|
484
|
+
totalConditions++;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
// Final check for total conditions
|
|
488
|
+
if (totalConditions > MAX_CONDITIONS) {
|
|
489
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Filter expression cannot exceed ${MAX_CONDITIONS} total conditions`);
|
|
490
|
+
}
|
|
491
|
+
// Type-safe return - Zod has validated the structure
|
|
492
|
+
return result;
|
|
493
|
+
}
|
|
494
|
+
catch (error) {
|
|
495
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
496
|
+
// Check for specific Zod errors and provide better error messages
|
|
497
|
+
const firstIssue = error.issues[0];
|
|
498
|
+
if (firstIssue) {
|
|
499
|
+
// Handle empty groups array
|
|
500
|
+
if (firstIssue.code === 'too_small' && firstIssue.path.length > 0 && firstIssue.path[firstIssue.path.length - 1] === 'groups') {
|
|
501
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Filter expression must have at least one group');
|
|
502
|
+
}
|
|
503
|
+
// Handle exceed maximum nesting depth or array size
|
|
504
|
+
if (firstIssue.code === 'too_big') {
|
|
505
|
+
if (firstIssue.message.includes('Array must contain at most 10 element(s)')) {
|
|
506
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Filter expression exceeds maximum nesting depth of 10');
|
|
507
|
+
}
|
|
508
|
+
if (firstIssue.message.includes('conditions') || firstIssue.message.includes('50') || firstIssue.message.includes('Array must contain at most 50')) {
|
|
509
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Filter expression cannot exceed 50 total conditions');
|
|
510
|
+
}
|
|
511
|
+
// Generic too_big error for filter expressions
|
|
512
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Filter expression exceeds maximum nesting depth of 10');
|
|
513
|
+
}
|
|
514
|
+
// Handle "Required" errors which might indicate missing required fields in deeply nested structures
|
|
515
|
+
if (firstIssue.code === 'invalid_type' && firstIssue.message === 'Required') {
|
|
516
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Filter expression exceeds maximum nesting depth of 10');
|
|
517
|
+
}
|
|
518
|
+
// Check if any issue mentions conditions or 50
|
|
519
|
+
if (error.issues.some(issue => issue.message.includes('conditions') ||
|
|
520
|
+
issue.message.includes('50') ||
|
|
521
|
+
issue.message.includes('Array must contain at most 50'))) {
|
|
522
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'Filter expression cannot exceed 50 total conditions');
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
const errorDetails = error.issues.map(issue => issue.message).join('; ');
|
|
526
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Invalid filter expression: ${errorDetails}`);
|
|
527
|
+
}
|
|
528
|
+
if (error instanceof errors_1.MCPError) {
|
|
529
|
+
throw error; // Re-throw MCPError as-is
|
|
530
|
+
}
|
|
531
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Filter expression validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Safely stringify JSON with comprehensive protection
|
|
536
|
+
* Prevents prototype pollution and sanitizes string values
|
|
537
|
+
*/
|
|
538
|
+
function safeJsonStringify(obj) {
|
|
539
|
+
try {
|
|
540
|
+
// Validate the object structure first - this will throw for invalid structures
|
|
541
|
+
const validated = validateFilterExpression(obj);
|
|
542
|
+
// Create a safe copy to prevent prototype pollution
|
|
543
|
+
const safeObj = createSafeObjectCopy(validated);
|
|
544
|
+
// Check for circular references before sanitizing
|
|
545
|
+
if (safeObj === null) {
|
|
546
|
+
throw new Error('Circular reference detected');
|
|
547
|
+
}
|
|
548
|
+
// Recursively sanitize string values in the object (but not operators)
|
|
549
|
+
const sanitizedObj = sanitizeObjectStrings(safeObj);
|
|
550
|
+
const jsonString = JSON.stringify(sanitizedObj);
|
|
551
|
+
return jsonString; // No need to sanitize the JSON string itself since we sanitized values
|
|
552
|
+
}
|
|
553
|
+
catch (error) {
|
|
554
|
+
if (error instanceof errors_1.MCPError) {
|
|
555
|
+
throw error; // Re-throw MCPError as-is
|
|
556
|
+
}
|
|
557
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Failed to stringify object: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Safely parse JSON with comprehensive protection
|
|
562
|
+
* Prevents prototype pollution and validates against dangerous content
|
|
563
|
+
*/
|
|
564
|
+
function safeJsonParse(jsonString) {
|
|
565
|
+
if (typeof jsonString !== 'string') {
|
|
566
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'JSON string must be a string');
|
|
567
|
+
}
|
|
568
|
+
// Check for maximum length
|
|
569
|
+
if (jsonString.length > 50000) {
|
|
570
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'JSON string exceeds maximum length');
|
|
571
|
+
}
|
|
572
|
+
// Check for prototype pollution patterns before parsing
|
|
573
|
+
if (containsPrototypePollution(jsonString)) {
|
|
574
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, 'JSON contains potentially dangerous prototype pollution patterns');
|
|
575
|
+
}
|
|
576
|
+
try {
|
|
577
|
+
const parsed = JSON.parse(jsonString);
|
|
578
|
+
// Create a safe copy to prevent prototype pollution attacks
|
|
579
|
+
const safeObj = createSafeObjectCopy(parsed);
|
|
580
|
+
// Validate and sanitize the parsed object
|
|
581
|
+
return validateFilterExpression(safeObj);
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
if (error instanceof SyntaxError) {
|
|
585
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Invalid JSON: ${error.message}`);
|
|
586
|
+
}
|
|
587
|
+
if (error instanceof errors_1.MCPError) {
|
|
588
|
+
throw error; // Re-throw our validation errors
|
|
589
|
+
}
|
|
590
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `Failed to parse JSON: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Validate ID parameters
|
|
595
|
+
*/
|
|
596
|
+
function validateId(id, fieldName) {
|
|
597
|
+
if (typeof id !== 'number' || !Number.isInteger(id) || id <= 0) {
|
|
598
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `${fieldName} must be a positive integer`);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Validate and convert ID from various formats
|
|
603
|
+
*/
|
|
604
|
+
function validateAndConvertId(id, fieldName) {
|
|
605
|
+
// Handle booleans - true converts to 1, false is rejected
|
|
606
|
+
if (typeof id === 'boolean') {
|
|
607
|
+
if (id === true) {
|
|
608
|
+
return 1;
|
|
609
|
+
}
|
|
610
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `${fieldName} must be a positive integer`);
|
|
611
|
+
}
|
|
612
|
+
if (typeof id === 'string') {
|
|
613
|
+
// Use Number() instead of parseInt for better conversion handling
|
|
614
|
+
// This handles hex strings like '0x42', exponential like '1e5', etc.
|
|
615
|
+
const parsed = Number(id);
|
|
616
|
+
if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed <= 0) {
|
|
617
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `${fieldName} must be a positive integer`);
|
|
618
|
+
}
|
|
619
|
+
return parsed;
|
|
620
|
+
}
|
|
621
|
+
if (typeof id === 'number') {
|
|
622
|
+
validateId(id, fieldName);
|
|
623
|
+
return id;
|
|
624
|
+
}
|
|
625
|
+
throw new errors_1.MCPError(errors_1.ErrorCode.VALIDATION_ERROR, `${fieldName} must be a number or positive integer string`);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Helper functions for comprehensive input sanitization
|
|
629
|
+
*/
|
|
630
|
+
/**
|
|
631
|
+
* Checks for prototype pollution patterns in JSON strings
|
|
632
|
+
*/
|
|
633
|
+
function containsPrototypePollution(jsonString) {
|
|
634
|
+
const lowerJson = jsonString.toLowerCase();
|
|
635
|
+
// Check for dangerous prototype pollution patterns
|
|
636
|
+
const pollutionPatterns = [
|
|
637
|
+
'__proto__',
|
|
638
|
+
'constructor',
|
|
639
|
+
'prototype',
|
|
640
|
+
'"__proto__":',
|
|
641
|
+
'"constructor":',
|
|
642
|
+
'"prototype":',
|
|
643
|
+
'"__proto__":',
|
|
644
|
+
'{"__proto__"',
|
|
645
|
+
'constructor.prototype',
|
|
646
|
+
'__defineGetter__',
|
|
647
|
+
'__defineSetter__',
|
|
648
|
+
'__lookupGetter__',
|
|
649
|
+
'__lookupSetter__'
|
|
650
|
+
];
|
|
651
|
+
return pollutionPatterns.some(pattern => lowerJson.includes(pattern));
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Creates a deep copy of an object while preventing prototype pollution
|
|
655
|
+
*/
|
|
656
|
+
function createSafeObjectCopy(obj, visited = new WeakSet()) {
|
|
657
|
+
// Handle null and primitive types
|
|
658
|
+
if (obj === null || typeof obj !== 'object') {
|
|
659
|
+
return obj;
|
|
660
|
+
}
|
|
661
|
+
// Prevent circular reference issues
|
|
662
|
+
if (visited.has(obj)) {
|
|
663
|
+
return null;
|
|
664
|
+
}
|
|
665
|
+
visited.add(obj);
|
|
666
|
+
// Handle arrays
|
|
667
|
+
if (Array.isArray(obj)) {
|
|
668
|
+
return obj.map(item => createSafeObjectCopy(item, visited));
|
|
669
|
+
}
|
|
670
|
+
// Handle Date objects
|
|
671
|
+
if (obj instanceof Date) {
|
|
672
|
+
return new Date(obj.getTime());
|
|
673
|
+
}
|
|
674
|
+
// Handle objects - create safe copy without prototype chain
|
|
675
|
+
const safeObj = {};
|
|
676
|
+
for (const key in obj) {
|
|
677
|
+
// Skip dangerous prototype properties
|
|
678
|
+
if (isSafeProperty(key)) {
|
|
679
|
+
try {
|
|
680
|
+
const value = obj[key];
|
|
681
|
+
safeObj[key] = createSafeObjectCopy(value, visited);
|
|
682
|
+
}
|
|
683
|
+
catch {
|
|
684
|
+
// Skip properties that cause errors during copying
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return safeObj;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Checks if a property key is safe (not dangerous for prototype pollution)
|
|
693
|
+
*/
|
|
694
|
+
function isSafeProperty(key) {
|
|
695
|
+
const dangerousKeys = [
|
|
696
|
+
'__proto__',
|
|
697
|
+
'constructor',
|
|
698
|
+
'prototype',
|
|
699
|
+
'__defineGetter__',
|
|
700
|
+
'__defineSetter__',
|
|
701
|
+
'__lookupGetter__',
|
|
702
|
+
'__lookupSetter__',
|
|
703
|
+
'hasOwnProperty',
|
|
704
|
+
'isPrototypeOf',
|
|
705
|
+
'propertyIsEnumerable',
|
|
706
|
+
'toLocaleString',
|
|
707
|
+
'toString',
|
|
708
|
+
'valueOf'
|
|
709
|
+
];
|
|
710
|
+
return !dangerousKeys.includes(key) && typeof key === 'string';
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Recursively sanitizes all string values in an object
|
|
714
|
+
* Skips known operator values to avoid HTML entity encoding
|
|
715
|
+
*/
|
|
716
|
+
function sanitizeObjectStrings(obj, visited = new WeakSet(), key = null) {
|
|
717
|
+
// Handle null and primitive types
|
|
718
|
+
if (obj === null || typeof obj !== 'object') {
|
|
719
|
+
if (typeof obj === 'string') {
|
|
720
|
+
// Don't sanitize known operator values
|
|
721
|
+
const knownOperators = ['=', '!=', '>', '>=', '<', '<=', 'like', 'in', 'not in', '&&', '||'];
|
|
722
|
+
if (knownOperators.includes(obj)) {
|
|
723
|
+
return obj;
|
|
724
|
+
}
|
|
725
|
+
return sanitizeString(obj);
|
|
726
|
+
}
|
|
727
|
+
return obj;
|
|
728
|
+
}
|
|
729
|
+
// Prevent circular reference issues
|
|
730
|
+
if (visited.has(obj)) {
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
visited.add(obj);
|
|
734
|
+
// Handle arrays
|
|
735
|
+
if (Array.isArray(obj)) {
|
|
736
|
+
return obj.map(item => sanitizeObjectStrings(item, visited, key));
|
|
737
|
+
}
|
|
738
|
+
// Handle Date objects (don't modify)
|
|
739
|
+
if (obj instanceof Date) {
|
|
740
|
+
return obj;
|
|
741
|
+
}
|
|
742
|
+
// Handle objects
|
|
743
|
+
const sanitizedObj = {};
|
|
744
|
+
for (const key in obj) {
|
|
745
|
+
if (isSafeProperty(key)) {
|
|
746
|
+
try {
|
|
747
|
+
const value = obj[key];
|
|
748
|
+
sanitizedObj[key] = sanitizeObjectStrings(value, visited, key);
|
|
749
|
+
}
|
|
750
|
+
catch {
|
|
751
|
+
// Skip properties that cause errors during sanitization
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return sanitizedObj;
|
|
757
|
+
}
|
|
758
|
+
//# sourceMappingURL=validation.js.map
|