From a50e868cb9ace356c7f2fc33e40d61ffa6a437ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 May 2026 12:38:34 +0100 Subject: [PATCH 01/13] chore (deps): bump tmp from 0.2.5 to 0.2.7 (#2479) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 89e5b3ec..3b48b92e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17352,9 +17352,9 @@ } }, "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, "license": "MIT", "engines": { From 53d6f0c746afe20175f394dd4c7ea0bd67bada4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 May 2026 12:44:28 +0100 Subject: [PATCH 02/13] chore (deps): bump qs and express (#2478) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 56 ++++++++++------------------------------------- 1 file changed, 12 insertions(+), 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3b48b92e..134641ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5972,9 +5972,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "dev": true, "license": "MIT", "dependencies": { @@ -5986,7 +5986,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -6070,22 +6070,6 @@ "node": ">= 0.8" } }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/body-parser/node_modules/raw-body": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", @@ -9442,15 +9426,15 @@ } }, "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "~1.20.3", + "body-parser": "~1.20.5", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", @@ -9469,7 +9453,7 @@ "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "~6.14.0", + "qs": "~6.15.1", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", @@ -9568,22 +9552,6 @@ "node": ">= 0.8" } }, - "node_modules/express/node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/express/node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -15368,9 +15336,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" From 89b5c7dee32a811f7c7cb06c07aaec1f8f226f44 Mon Sep 17 00:00:00 2001 From: GCHQ Developer 85297 <95289555+C85297@users.noreply.github.com> Date: Tue, 2 Jun 2026 20:35:21 +0100 Subject: [PATCH 03/13] Fix option ingredients being overwriten (#2341) --- src/web/HTMLIngredient.mjs | 1 + src/web/waiters/RecipeWaiter.mjs | 10 ++++++- tests/browser/03_recipe_load.js | 48 ++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 tests/browser/03_recipe_load.js diff --git a/src/web/HTMLIngredient.mjs b/src/web/HTMLIngredient.mjs index 91cbed89..9f61b75a 100755 --- a/src/web/HTMLIngredient.mjs +++ b/src/web/HTMLIngredient.mjs @@ -166,6 +166,7 @@ class HTMLIngredient { id="${this.id}" tabindex="${this.tabIndex}" arg-name="${this.name}" + data-target="${this.target}" ${this.disabled ? "disabled" : ""}>`; for (i = 0; i < this.value.length; i++) { if ((m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) { diff --git a/src/web/waiters/RecipeWaiter.mjs b/src/web/waiters/RecipeWaiter.mjs index 4272ef3b..e4198cd5 100755 --- a/src/web/waiters/RecipeWaiter.mjs +++ b/src/web/waiters/RecipeWaiter.mjs @@ -487,11 +487,19 @@ class RecipeWaiter { * @param {HTMLElement} op */ triggerArgEvents(op) { - // Trigger populateOption and argSelector events + // Trigger argSelector events and populateOption events only where the target is empty. + // When loading a saved recipe, arguments are populated before this method is called, so + // re-triggering populateOption events would overwrite saved custom values with defaults. + const args = op.querySelectorAll(".arg"); const triggerableOptions = op.querySelectorAll(".populate-option, .arg-selector"); const evt = new Event("change", {bubbles: true}); + if (triggerableOptions.length) { for (const el of triggerableOptions) { + if (el.classList.contains("populate-option")) { + const target = args[el.getAttribute("data-target")]; + if (target && target.value !== "") continue; + } el.dispatchEvent(evt); } } diff --git a/tests/browser/03_recipe_load.js b/tests/browser/03_recipe_load.js new file mode 100644 index 00000000..58609d99 --- /dev/null +++ b/tests/browser/03_recipe_load.js @@ -0,0 +1,48 @@ +/** + * Regression tests for recipe loading behaviour. + * + * @author C85297 [95289555+C85297@users.noreply.github.com] + * @copyright Crown Copyright + * @license Apache-2.0 + */ + +const utils = require("./browserUtils.js"); + +module.exports = { + before: browser => { + browser + .resizeWindow(1280, 800) + .url(browser.launchUrl) + .useCss() + .waitForElementNotPresent("#preloader", 10000); + }, + + "Recipe load preserves populated arguments": browser => { + const inputFormat = "HH:mm:ss a MMM DD, YYYY "; + const input = "10:20:30 pm Sep 26, 2019 "; + + utils.loadRecipe( + browser, + "Translate DateTime Format", + input, + [ + "Standard date and time", + inputFormat, + "UTC", + "DD/MM/YYYY HH:mm:ss", + "UTC" + ] + ); + + browser.execute(() => { + return Array.from(document.querySelectorAll("#rec-list li.operation .arg")) + .map(arg => arg.value); + }, [], function({value}) { + browser.expect(value[1]).to.equal(inputFormat); + }); + }, + + after: browser => { + browser.end(); + } +}; From 72ca1aeec7a50f4c596d44b755a6ca71f792ffcf Mon Sep 17 00:00:00 2001 From: A Normal Ladd Date: Wed, 3 Jun 2026 03:57:13 -0600 Subject: [PATCH 04/13] Add remove ANSI escape codes operation (#2143) Co-authored-by: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> (additional test case) --- src/core/config/Categories.json | 1 + src/core/operations/RemoveANSIEscapeCodes.mjs | 41 ++++++++++++ tests/operations/index.mjs | 1 + .../tests/RemoveANSIEscapeCodes.mjs | 62 +++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 src/core/operations/RemoveANSIEscapeCodes.mjs create mode 100644 tests/operations/tests/RemoveANSIEscapeCodes.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 3404dc6d..dd6918dc 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -304,6 +304,7 @@ "Diff", "Remove whitespace", "Remove null bytes", + "Remove ANSI Escape Codes", "To Upper case", "To Lower case", "Swap case", diff --git a/src/core/operations/RemoveANSIEscapeCodes.mjs b/src/core/operations/RemoveANSIEscapeCodes.mjs new file mode 100644 index 00000000..2301f852 --- /dev/null +++ b/src/core/operations/RemoveANSIEscapeCodes.mjs @@ -0,0 +1,41 @@ +/** + * @author Louis-Ladd [lewisharshman1@gmail.com] + * @copyright Crown Copyright 2025 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * Remove ANSI Escape Codes operation + */ +class RemoveANSIEscapeCodes extends Operation { + + /** + * RemoveANSIEscapeCodes constructor + */ + constructor() { + super(); + + this.name = "Remove ANSI Escape Codes"; + this.module = "Default"; + this.description = "Removes ANSI Escape Codes."; + this.infoURL = "https://wikipedia.org/wiki/ANSI_escape_code"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const ansiRegex = /\x1B\[[0-?]*[ -/]*[@-~]/g; + return input.replace(ansiRegex, ""); + } + +} + +export default RemoveANSIEscapeCodes; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index c12c2710..c44270fd 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -148,6 +148,7 @@ import "./tests/Rabbit.mjs"; import "./tests/RAKE.mjs"; import "./tests/Regex.mjs"; import "./tests/Register.mjs"; +import "./tests/RemoveANSIEscapeCodes.mjs"; import "./tests/RegularExpression.mjs"; import "./tests/RenderMarkdown.mjs"; import "./tests/RisonEncodeDecode.mjs"; diff --git a/tests/operations/tests/RemoveANSIEscapeCodes.mjs b/tests/operations/tests/RemoveANSIEscapeCodes.mjs new file mode 100644 index 00000000..491795c3 --- /dev/null +++ b/tests/operations/tests/RemoveANSIEscapeCodes.mjs @@ -0,0 +1,62 @@ +/** + * @author Louis-Ladd [lewisharshman1@gmail.com] + * @copyright Crown Copyright 2025 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + "name": "Remove ANSI Escape Codes: text using x1b escape code", + "input": "\x1b[31mHello, \x1b[31mWorld!", + "expectedOutput": "Hello, World!", + "recipeConfig": [ + { + "op": "Remove ANSI Escape Codes", + "args": [], + }, + ], + }, + { + "name": "Remove ANSI Escape Codes: text with incomplete codes", + "input": "\x1b[31 Hello, World!", + "expectedOutput": "ello, World!", + "recipeConfig": [ + { + "op": "Remove ANSI Escape Codes", + "args": [], + }, + ], + }, + { + "name": "Remove ANSI Escape Codes: cursor commands and clear screen", + "input": "\x1b[2J\x1b[H\x1b[3BHello, World!", + "expectedOutput": "Hello, World!", + "recipeConfig": [ + { + "op": "Remove ANSI Escape Codes", + "args": [], + }, + ], + }, + { + "name": "Remove ANSI Escape Codes: text containing javascript escape representation of ansi escape codes", + // input/output expressed in hex to avoid accidental interpretation of Javascript escapes and to make the test case explicit + "input": "5c 30 33 33 5b 33 32 3b 31 3b 33 3b 34 3b 39 6d 48 65 6c 6c 6f 2c 20 5c 30 33 33 5b 33 32 3b 31 3b 33 3b 34 3b 39 6d 57 6f 72 6c 64 21", + "expectedOutput": "5c 30 33 33 5b 33 32 3b 31 3b 33 3b 34 3b 39 6d 48 65 6c 6c 6f 2c 20 5c 30 33 33 5b 33 32 3b 31 3b 33 3b 34 3b 39 6d 57 6f 72 6c 64 21", + "recipeConfig": [ + { + "op": "From Hex", + "args": ["Auto"] + }, + { + "op": "Remove ANSI Escape Codes", + "args": [] + }, + { + "op": "To Hex", + "args": ["Space", 0] + } + ], + }, +]); From 5318bab19fe842a0696a40317c779d105e7df16c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:40:18 +0100 Subject: [PATCH 05/13] chore (deps): bump nginxinc/nginx-unprivileged from `df0e9ed` to `0a1e718` in the docker-dependencies group (#2498) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 864f1606..6e6ee6f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN npm run build ######################################### # Package static build files into nginx # ######################################### -FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:df0e9edf92b8436ff797fe5a2cbfc66be1df775c113d322ccadf5c7f3100eda8 AS cyberchef +FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:0a1e718ff1e1a22fc519d0c2e5b6872681f01e37c8a2817ec43ce6e716103929 AS cyberchef LABEL maintainer="GCHQ " From 8a5c60ac74d445073ca012bdcf118281098155ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:47:23 +0100 Subject: [PATCH 06/13] chore (deps): bump the patch-updates group with 2 updates (#2499) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 16 ++++++++-------- package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 134641ce..f3e9e881 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "d3": "7.9.0", "d3-hexbin": "^0.2.2", "diff": "^5.2.2", - "dompurify": "^3.4.6", + "dompurify": "^3.4.7", "es6-promisify": "^7.0.0", "escodegen": "^2.1.0", "esprima": "^4.0.1", @@ -85,7 +85,7 @@ "path": "^0.12.7", "popper.js": "^1.16.1", "process": "^0.11.10", - "protobufjs": "^7.6.1", + "protobufjs": "^7.6.2", "punycode.js": "^2.3.1", "qr-image": "^3.2.0", "reflect-metadata": "^0.2.2", @@ -8620,9 +8620,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.6.tgz", - "integrity": "sha512-+7gzEI8trIIQkVCvQ3ucGtNfH3nOmDgVTzc62rAAOlMxLth78pwpPoZCPc7CyRzAQF89MqcfPdEWkDwnjgqktg==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.7.tgz", + "integrity": "sha512-2jBxDJY4RR06tQNy4w5FlFH7kfxsQZlufd0sbv+chfHCxeJwrFw2baUDsSwvBISD4K4RDbd0PTfy3uNXsR6siA==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -15101,9 +15101,9 @@ "license": "MIT" }, "node_modules/protobufjs": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.1.tgz", - "integrity": "sha512-4K0myLaWL5EteuSAro91EGFgcfVgxb64Jx+7oDAY6GOkXD4M69yuSEljNcInGVCA5sOPxmZ/EqDLj2x0Q0+Ygg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.2.tgz", + "integrity": "sha512-N9EiLovGEQOJSPF26Ij7qUGvahfEnq0eeYZ02aigIedkmz1qZSwjnP9SBITHJuF/6MYbIW4HDN8zdYjsjqJKXQ==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { diff --git a/package.json b/package.json index d7d1b48a..6faf49f3 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,7 @@ "d3": "7.9.0", "d3-hexbin": "^0.2.2", "diff": "^5.2.2", - "dompurify": "^3.4.6", + "dompurify": "^3.4.7", "es6-promisify": "^7.0.0", "escodegen": "^2.1.0", "esprima": "^4.0.1", @@ -169,7 +169,7 @@ "path": "^0.12.7", "popper.js": "^1.16.1", "process": "^0.11.10", - "protobufjs": "^7.6.1", + "protobufjs": "^7.6.2", "punycode.js": "^2.3.1", "qr-image": "^3.2.0", "reflect-metadata": "^0.2.2", From 3034d63f90f3e2d5b3079fc7f4f0d774131b05f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 10:26:43 +0100 Subject: [PATCH 07/13] chore (deps): bump the minor-updates group with 5 updates (#2500) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> (removed jq-web update, and added it to dependabot.yml block list) --- .github/dependabot.yml | 2 ++ package-lock.json | 77 +++++++++++++++++++++++------------------- package.json | 8 ++--- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ded5077c..16cd1c3a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -41,6 +41,8 @@ updates: versions: [ '>=2.0.0' ] - dependency-name: 'jimp' versions: [ '1.6.1' ] + - dependency-name: 'jq-web' + versions: [ '>=0.6.0' ] groups: # # Grouping so patch version updates are batched together in a single PR diff --git a/package-lock.json b/package-lock.json index f3e9e881..623c8440 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,7 +58,7 @@ "js-sha3": "^0.9.3", "jsesc": "^3.1.0", "json5": "^2.2.3", - "jsonata": "^2.1.0", + "jsonata": "^2.2.1", "jsonpath-plus": "^10.4.0", "jsonwebtoken": "9.0.3", "jsqr": "^1.4.0", @@ -71,7 +71,7 @@ "loglevel-message-prefix": "^3.0.0", "lz-string": "^1.5.0", "lz4js": "^0.2.0", - "markdown-it": "^14.1.1", + "markdown-it": "^14.2.0", "moment": "^2.30.1", "moment-timezone": "^0.6.2", "ngeohash": "^0.6.3", @@ -109,7 +109,7 @@ "zlibjs": "^0.3.1" }, "devDependencies": { - "@babel/eslint-parser": "^7.28.6", + "@babel/eslint-parser": "^7.29.7", "@babel/plugin-syntax-import-assertions": "^7.28.6", "@babel/plugin-transform-runtime": "^7.29.7", "@babel/preset-env": "^7.29.7", @@ -149,7 +149,7 @@ "imports-loader": "^5.0.0", "mini-css-extract-plugin": "2.10.2", "modify-source-webpack-plugin": "^4.1.0", - "nightwatch": "^3.15.0", + "nightwatch": "^3.16.0", "postcss": "^8.5.15", "postcss-css-variables": "^0.19.0", "postcss-import": "^16.1.1", @@ -279,9 +279,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz", - "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.29.7.tgz", + "integrity": "sha512-zxt+UJTOMKvUt3yOg+D58MLuz334pHp93qifMFcjIIO+9hN6t+ufw2gi7vDPMpxvfnHRR+3VVXvIjineCcgyXw==", "dev": true, "license": "MIT", "dependencies": { @@ -12413,9 +12413,9 @@ } }, "node_modules/jsonata": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.1.0.tgz", - "integrity": "sha512-OCzaRMK8HobtX8fp37uIVmL8CY1IGc/a6gLsDqz3quExFR09/U78HUzWYr7T31UEB6+Eu0/8dkVD5fFDOl9a8w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.2.1.tgz", + "integrity": "sha512-xd1uwUrKeIcJbsWhaoS3qAX4Ea8m0Mw0G5nlnAQvPT7TbZ5qaPdzBVTQia9KfyuyQm+nenfyjvzUDTRYHsC2sw==", "license": "MIT", "engines": { "node": ">= 8" @@ -12683,9 +12683,19 @@ "license": "MIT" }, "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" @@ -13002,14 +13012,24 @@ } }, "node_modules/markdown-it": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", - "linkify-it": "^5.0.0", + "linkify-it": "^5.0.1", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" @@ -13557,9 +13577,9 @@ } }, "node_modules/nightwatch": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-3.15.0.tgz", - "integrity": "sha512-Vvh7TsDyEN1YzOsDNoafEUPJDQ6jfnmJPAsWo/EmygljZiRk1Ja/pEqNAhE5UdYJzF38SNO46gJS8IRk9mUNfA==", + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-3.16.0.tgz", + "integrity": "sha512-B0/zFPY5ujEwIWIPqo2ClgITZ3chB3Nfq86YNWCyE3/P8BrCSvv2Y6BNUA+9mgu8WM/XF6GNlV3LONzZ1S+JSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13584,7 +13604,7 @@ "glob": "7.2.3", "jsdom": "^24.1.0", "lodash": "^4.17.21", - "minimatch": "3.1.2", + "minimatch": "3.1.5", "minimist": "1.2.6", "mocha": "10.8.2", "nightwatch-axe-verbose": "^2.3.0", @@ -13602,7 +13622,7 @@ "nightwatch": "bin/nightwatch" }, "engines": { - "node": ">= 16" + "node": ">= 18.20.5" }, "peerDependencies": { "@cucumber/cucumber": "*" @@ -13681,19 +13701,6 @@ "node": ">=10" } }, - "node_modules/nightwatch/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/nightwatch/node_modules/minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", diff --git a/package.json b/package.json index 6faf49f3..8a82b685 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "node >= 24" ], "devDependencies": { - "@babel/eslint-parser": "^7.28.6", + "@babel/eslint-parser": "^7.29.7", "@babel/plugin-syntax-import-assertions": "^7.28.6", "@babel/plugin-transform-runtime": "^7.29.7", "@babel/preset-env": "^7.29.7", @@ -79,7 +79,7 @@ "imports-loader": "^5.0.0", "mini-css-extract-plugin": "2.10.2", "modify-source-webpack-plugin": "^4.1.0", - "nightwatch": "^3.15.0", + "nightwatch": "^3.16.0", "postcss": "^8.5.15", "postcss-css-variables": "^0.19.0", "postcss-import": "^16.1.1", @@ -142,7 +142,7 @@ "js-sha3": "^0.9.3", "jsesc": "^3.1.0", "json5": "^2.2.3", - "jsonata": "^2.1.0", + "jsonata": "^2.2.1", "jsonpath-plus": "^10.4.0", "jsonwebtoken": "9.0.3", "jsqr": "^1.4.0", @@ -155,7 +155,7 @@ "loglevel-message-prefix": "^3.0.0", "lz-string": "^1.5.0", "lz4js": "^0.2.0", - "markdown-it": "^14.1.1", + "markdown-it": "^14.2.0", "moment": "^2.30.1", "moment-timezone": "^0.6.2", "ngeohash": "^0.6.3", From 20b46bf1a0a788fbb9bd095ed45e3bb2e1d548f8 Mon Sep 17 00:00:00 2001 From: Syed Ishmum Ahnaf Date: Fri, 5 Jun 2026 15:47:48 +0600 Subject: [PATCH 08/13] fix: validate text encoding options (#2497) --- src/core/operations/DecodeText.mjs | 4 ++++ src/core/operations/EncodeText.mjs | 4 ++++ tests/operations/tests/CharEnc.mjs | 26 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/core/operations/DecodeText.mjs b/src/core/operations/DecodeText.mjs index 0fc9d2b5..baf23336 100644 --- a/src/core/operations/DecodeText.mjs +++ b/src/core/operations/DecodeText.mjs @@ -5,6 +5,7 @@ */ import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; import cptable from "codepage"; import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs"; @@ -48,6 +49,9 @@ class DecodeText extends Operation { */ run(input, args) { const format = CHR_ENC_CODE_PAGES[args[0]]; + if (!format) { + throw new OperationError("Invalid encoding"); + } return cptable.utils.decode(format, new Uint8Array(input)); } diff --git a/src/core/operations/EncodeText.mjs b/src/core/operations/EncodeText.mjs index 8cc1450f..5cc09742 100644 --- a/src/core/operations/EncodeText.mjs +++ b/src/core/operations/EncodeText.mjs @@ -5,6 +5,7 @@ */ import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; import cptable from "codepage"; import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs"; @@ -48,6 +49,9 @@ class EncodeText extends Operation { */ run(input, args) { const format = CHR_ENC_CODE_PAGES[args[0]]; + if (!format) { + throw new OperationError("Invalid encoding"); + } const encoded = cptable.utils.encode(format, input); return new Uint8Array(encoded).buffer; } diff --git a/tests/operations/tests/CharEnc.mjs b/tests/operations/tests/CharEnc.mjs index eecfaab6..83f71ca9 100644 --- a/tests/operations/tests/CharEnc.mjs +++ b/tests/operations/tests/CharEnc.mjs @@ -68,6 +68,32 @@ TestRegister.addTests([ }, ], }, + { + name: "Encode text: empty encoding", + input: "hello", + expectedOutput: "Invalid encoding", + recipeConfig: [ + { + "op": "Encode text", + "args": [""] + }, + ], + }, + { + name: "Decode text: empty encoding", + input: "68 65 6c 6c 6f", + expectedOutput: "Invalid encoding", + recipeConfig: [ + { + "op": "From Hex", + "args": ["Space"] + }, + { + "op": "Decode text", + "args": [""] + }, + ], + }, { name: "Generate Base64 Windows PowerShell", input: "ZABpAHIAIAAiAGMAOgBcAHAAcgBvAGcAcgBhAG0AIABmAGkAbABlAHMAIgAgAA==", From da202d54f160fb07728f7070b4eccd1b765543cb Mon Sep 17 00:00:00 2001 From: andreas Date: Fri, 5 Jun 2026 12:23:38 +0200 Subject: [PATCH 09/13] feat: Get AES IV from input (QoL) (#2471) --- src/core/operations/AESDecrypt.mjs | 77 ++++-- src/core/operations/AESEncrypt.mjs | 37 ++- tests/browser/02_ops.js | 4 +- tests/node/tests/operations.mjs | 39 ++++ tests/operations/tests/Crypt.mjs | 350 +++++++++++++++++++++++----- tests/operations/tests/Register.mjs | 4 +- 6 files changed, 419 insertions(+), 92 deletions(-) diff --git a/src/core/operations/AESDecrypt.mjs b/src/core/operations/AESDecrypt.mjs index 5e6cec26..44e6cab2 100644 --- a/src/core/operations/AESDecrypt.mjs +++ b/src/core/operations/AESDecrypt.mjs @@ -39,41 +39,46 @@ class AESDecrypt extends Operation { "value": "", "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] }, + { + "name": "IV Length", + "type": "number", + "value": 16 + }, { "name": "Mode", "type": "argSelector", "value": [ { name: "CBC", - off: [5, 6] + off: [6, 7] }, { name: "CFB", - off: [5, 6] + off: [6, 7] }, { name: "OFB", - off: [5, 6] + off: [6, 7] }, { name: "CTR", - off: [5, 6] + off: [6, 7] }, { name: "GCM", - on: [5, 6] + on: [6, 7] }, { name: "ECB", - off: [5, 6] + off: [6, 7] }, { name: "CBC/NoPadding", - off: [5, 6] + off: [6, 7] }, { name: "ECB/NoPadding", - off: [5, 6] + off: [6, 7] } ] }, @@ -98,6 +103,26 @@ class AESDecrypt extends Operation { "type": "toggleString", "value": "", "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV from input", + "type": "argSelector", + "value": [ + { + name: "Off", + on: [1], + off: [2] + }, + { + name: "From start", + on: [2], + off: [1] + }, { + name: "From end", + on: [2], + off: [1] + } + ] } ]; } @@ -110,14 +135,18 @@ class AESDecrypt extends Operation { * @throws {OperationError} if cannot decrypt input or invalid key length */ run(input, args) { + let iv; + const key = Utils.convertToByteString(args[0].string, args[0].option), - iv = Utils.convertToByteString(args[1].string, args[1].option), - mode = args[2].split("/")[0], - noPadding = args[2].endsWith("NoPadding"), - inputType = args[3], - outputType = args[4], - gcmTag = Utils.convertToByteString(args[5].string, args[5].option), - aad = Utils.convertToByteString(args[6].string, args[6].option); + ivLength = args[2], + mode = args[3].split("/")[0], + noPadding = args[3].endsWith("NoPadding"), + inputType = args[4], + outputType = args[5], + gcmTag = Utils.convertToByteString(args[6].string, args[6].option), + aad = Utils.convertToByteString(args[7].string, args[7].option), + ivFromInput = args[8]; + if ([16, 24, 32].indexOf(key.length) < 0) { throw new OperationError(`Invalid key length: ${key.length} bytes @@ -130,11 +159,27 @@ The following algorithms will be used based on the size of the key: input = Utils.convertToByteString(input, inputType); + if (ivFromInput !== "Off") { + if (input.length <= ivLength) { + throw new OperationError(`Input is too short to contain an IV of ${ivLength} bytes.`); + } + + if (ivFromInput === "From start") { + iv = input.substr(0, ivLength); + input = input.substr(ivLength); + } else { + iv = input.substr(input.length - ivLength); + input = input.substr(0, input.length - ivLength); + } + } else { + iv = Utils.convertToByteString(args[1].string, args[1].option); + } + const decipher = forge.cipher.createDecipher("AES-" + mode, key); /* Allow for a "no padding" mode */ if (noPadding) { - decipher.mode.unpad = function(output, options) { + decipher.mode.unpad = function (output, options) { return true; }; } diff --git a/src/core/operations/AESEncrypt.mjs b/src/core/operations/AESEncrypt.mjs index 84e1c540..8a1c25de 100644 --- a/src/core/operations/AESEncrypt.mjs +++ b/src/core/operations/AESEncrypt.mjs @@ -8,6 +8,7 @@ import Operation from "../Operation.mjs"; import Utils from "../Utils.mjs"; import forge from "node-forge"; import OperationError from "../errors/OperationError.mjs"; +import { toHexFast } from "../lib/Hex.mjs"; /** * AES Encrypt operation @@ -92,6 +93,11 @@ class AESEncrypt extends Operation { "type": "toggleString", "value": "", "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "Include IV in output", + "type": "option", + "value": ["Off", "Prepend", "Append"] } ]; } @@ -107,10 +113,11 @@ class AESEncrypt extends Operation { const key = Utils.convertToByteString(args[0].string, args[0].option), iv = Utils.convertToByteString(args[1].string, args[1].option), mode = args[2].split("/")[0], - noPadding = args[2].endsWith("NoPadding"), + noPadding = args[2].endsWith("NoPadding"), inputType = args[3], outputType = args[4], - aad = Utils.convertToByteString(args[5].string, args[5].option); + aad = Utils.convertToByteString(args[5].string, args[5].option), + includeIV = args[6]; if ([16, 24, 32].indexOf(key.length) < 0) { throw new OperationError(`Invalid key length: ${key.length} bytes @@ -133,26 +140,34 @@ The following algorithms will be used based on the size of the key: additionalData: mode === "GCM" ? aad : undefined }); if (noPadding) { - cipher.mode.pad = function(output, options) { + cipher.mode.pad = function (output, options) { return true; }; } cipher.update(forge.util.createBuffer(input)); cipher.finish(); + let output = cipher.output.getBytes(); + + if (includeIV === "Prepend") { + output = iv + output; + } else if (includeIV === "Append") { + output = output + iv; + } + if (outputType === "Hex") { + output = toHexFast(Utils.strToByteArray(output)); + if (mode === "GCM") { - return cipher.output.toHex() + "\n\n" + + return output + "\n\n" + "Tag: " + cipher.mode.tag.toHex(); } - return cipher.output.toHex(); - } else { - if (mode === "GCM") { - return cipher.output.getBytes() + "\n\n" + - "Tag: " + cipher.mode.tag.getBytes(); - } - return cipher.output.getBytes(); + } else if (mode === "GCM") { + return output + "\n\n" + + "Tag: " + cipher.mode.tag.getBytes(); } + + return output; } } diff --git a/tests/browser/02_ops.js b/tests/browser/02_ops.js index 9d29f50d..32bd14d6 100644 --- a/tests/browser/02_ops.js +++ b/tests/browser/02_ops.js @@ -30,8 +30,8 @@ module.exports = { testOp(browser, "A1Z26 Cipher Decode", "20 5 19 20 15 21 20 16 21 20", "testoutput"); testOp(browser, "A1Z26 Cipher Encode", "test input", "20 5 19 20 9 14 16 21 20"); testOp(browser, "ADD", "test input", "Ê»ÉÊv¿ÄÆËÊ", [{ "option": "Hex", "string": "56" }]); - testOp(browser, "AES Decrypt", "b443f7f7c16ac5396a34273f6f639caa", "test output", [{ "option": "Hex", "string": "00112233445566778899aabbccddeeff" }, { "option": "Hex", "string": "00000000000000000000000000000000" }, "CBC", "Hex", "Raw", { "option": "Hex", "string": "" }]); - testOp(browser, "AES Encrypt", "test input", "e42eb8fbfb7a98fff061cd2c1a794d92", [{"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CBC", "Raw", "Hex"]); + testOp(browser, "AES Decrypt", "b443f7f7c16ac5396a34273f6f639caa", "test output", [{ "option": "Hex", "string": "00112233445566778899aabbccddeeff" }, { "option": "Hex", "string": "00000000000000000000000000000000" }, 16, "CBC", "Hex", "Raw", { "option": "Hex", "string": "" }, { "option": "Hex", "string": "" }, "Off"]); + testOp(browser, "AES Encrypt", "test input", "e42eb8fbfb7a98fff061cd2c1a794d92", [{"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CBC", "Raw", "Hex", "Off"]); testOp(browser, "AND", "test input", "4$04 $044", [{ "option": "Hex", "string": "34" }]); testOp(browser, "Add line numbers", "test input", "1 test input"); testOp(browser, ["From Hex", "Add Text To Image", "SHA2"], Images.PNG_HEX, "50cdf8ea483c55564a091650c2bccb4586f919b721e5fe9d6a61660505b4346d6ebdb2ef0cf075a7728cd84cb26ea3e477b5bd86a94a49a27d79423994afb60a", [[], ["Chef", "Center", "Middle", 0, 0, 16, "Roboto"], []]); diff --git a/tests/node/tests/operations.mjs b/tests/node/tests/operations.mjs index 3b2bbda6..6cf85718 100644 --- a/tests/node/tests/operations.mjs +++ b/tests/node/tests/operations.mjs @@ -79,7 +79,46 @@ TestRegister.addApiTests([ string: "some iv some iv1", option: "utf8", }, + ivLength: 16, mode: "OFB", + inputType: "Hex", + outputType: "Raw", + gcmTag: { + option: "Hex", + string: "" + }, + aad: { + option: "Hex", + string: "" + }, + ivFromInput: "Off" + }); + assert.equal(result.toString(), "a slightly longer sampleinput?"); + }), + + it("AES decrypt: IV from input", () => { + const result = AESDecrypt("4a123af235a507bbc9d5871721d61b98504d569a9a5a7847e2d78315fec7736f6d6520697620736f6d6520697631", { + key: { + string: "some longer key1", + option: "utf8", + }, + iv: { + string: "", + option: "Hex", + }, + ivLength: 16, + mode: "OFB", + inputType: "Hex", + outputType: "Raw", + gcmTag: { + option: "Hex", + string: "" + }, + aad: { + option: "Hex", + string: "" + }, + ivFromInput: "From end" }); assert.equal(result.toString(), "a slightly longer sampleinput?"); }), diff --git a/tests/operations/tests/Crypt.mjs b/tests/operations/tests/Crypt.mjs index 504f64b9..18b1c6e5 100644 --- a/tests/operations/tests/Crypt.mjs +++ b/tests/operations/tests/Crypt.mjs @@ -74,7 +74,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": ""}, {"option": "Hex", "string": ""}, "CBC", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -90,7 +91,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CBC", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -106,7 +108,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, "CTR", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -122,7 +125,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, "CBC", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -138,7 +142,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, "CFB", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -154,7 +159,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, "OFB", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -170,7 +176,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, "CTR", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -186,7 +193,8 @@ The following algorithms will be used based on the size of the key: {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": ""}, "ECB", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -204,7 +212,8 @@ Tag: 16a3e732a605cc9ca29108f742ca0743`, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": ""}, "GCM", "Raw", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -222,7 +231,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"}, "GCM", "Raw", "Hex", - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -238,7 +248,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CBC", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -254,7 +265,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -270,7 +282,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "OFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -286,7 +299,8 @@ Tag: 3b5378917f67b0aade9891fc6c291646`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CTR", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -304,7 +318,8 @@ Tag: 70fad2ca19412c20f40fd06918736e56`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -322,7 +337,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -338,7 +354,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "ECB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -354,7 +371,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CBC", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -370,7 +388,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -386,7 +405,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "OFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -402,7 +422,8 @@ Tag: 61cc4b70809452b0b3e38f913fa0a109`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CTR", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -420,7 +441,8 @@ Tag: 86db597d5302595223cadbd990f1309b`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -438,7 +460,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -454,7 +477,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "ECB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -470,7 +494,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CBC", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -486,7 +511,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -502,7 +528,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "OFB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -518,7 +545,8 @@ Tag: aeedf3e6ca4201577c0cf3e9ce58159d`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "CTR", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -536,7 +564,8 @@ Tag: 821b1e5f32dad052e502775a523d957a`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -554,7 +583,8 @@ Tag: a8f04c4d93bbef82bef61a103371aef9`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "GCM", "Hex", "Hex", - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -570,7 +600,46 @@ Tag: a8f04c4d93bbef82bef61a103371aef9`, {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, "ECB", "Hex", "Hex", - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" + ] + } + ], + }, + { + name: "AES Encrypt: AES-256-GCM, Binary, AAD, prepend IV to output", + input: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + expectedOutput: `1748e7179bd56570d51fa4ba287cc3e51287f188ad4d7ab0d9ff69b3c29cb11f861389532d8cb9337181da2e8cfc74a84927e8c0dd7a28a32fd485afe694259a63c199b199b95edd87c7aa95329feac340f2b78b72956a85f367044d821766b1b7135815571df44900695f1518cf3ae38ecb650f + +Tag: a8f04c4d93bbef82bef61a103371aef9`, + recipeConfig: [ + { + "op": "AES Encrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + "GCM", "Hex", "Hex", + {"option": "UTF8", "string": "additional data"}, + "Prepend" + ] + } + ], + }, + { + name: "AES Encrypt: AES-256-GCM, Binary, AAD, append IV to output", + input: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + expectedOutput: `1287f188ad4d7ab0d9ff69b3c29cb11f861389532d8cb9337181da2e8cfc74a84927e8c0dd7a28a32fd485afe694259a63c199b199b95edd87c7aa95329feac340f2b78b72956a85f367044d821766b1b7135815571df44900695f1518cf3ae38ecb650f1748e7179bd56570d51fa4ba287cc3e5 + +Tag: a8f04c4d93bbef82bef61a103371aef9`, + recipeConfig: [ + { + "op": "AES Encrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + "GCM", "Hex", "Hex", + {"option": "UTF8", "string": "additional data"}, + "Append" ] } ], @@ -776,9 +845,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": ""}, {"option": "Hex", "string": ""}, + 16, "CBC", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -793,9 +864,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, + 16, "CBC", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -810,9 +883,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00000000000000000000000000000000"}, + 16, "CTR", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -827,9 +902,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, + 16, "CBC", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -844,9 +921,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, + 16, "CFB", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -861,9 +940,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, + 16, "OFB", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -878,9 +959,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, + 16, "CTR", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -895,9 +978,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": ""}, + 16, "ECB", "Hex", "Raw", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -912,9 +997,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": ""}, + 16, "GCM", "Hex", "Raw", {"option": "Hex", "string": "16a3e732a605cc9ca29108f742ca0743"}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -929,9 +1016,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "00112233445566778899aabbccddeeff"}, {"option": "Hex", "string": "ffeeddccbbaa99887766554433221100"}, + 16, "GCM", "Hex", "Raw", {"option": "Hex", "string": "3b5378917f67b0aade9891fc6c291646"}, - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -946,9 +1035,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CBC", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -963,9 +1054,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -980,9 +1073,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "OFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -997,9 +1092,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CTR", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1014,9 +1111,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "70fad2ca19412c20f40fd06918736e56"}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1031,9 +1130,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "61cc4b70809452b0b3e38f913fa0a109"}, - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -1048,9 +1149,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "51e201d463698ef5f717f71f5b4712af"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "ECB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1065,9 +1168,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CBC", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1082,9 +1187,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1099,9 +1206,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "OFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1116,9 +1225,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CTR", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1133,9 +1244,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "86db597d5302595223cadbd990f1309b"}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1150,9 +1263,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "aeedf3e6ca4201577c0cf3e9ce58159d"}, - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -1167,9 +1282,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "6801ed503c9d96ee5f9d78b07ab1b295dba3c2adf81c7816"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "ECB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1184,9 +1301,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CBC", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1201,9 +1320,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1218,9 +1339,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "OFB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1235,9 +1358,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "CTR", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1252,9 +1377,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "821b1e5f32dad052e502775a523d957a"}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" ] } ], @@ -1269,9 +1396,11 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "GCM", "Hex", "Hex", {"option": "Hex", "string": "a8f04c4d93bbef82bef61a103371aef9"}, - {"option": "UTF8", "string": "additional data"} + {"option": "UTF8", "string": "additional data"}, + "Off" ] } ], @@ -1286,9 +1415,106 @@ The following algorithms will be used based on the size of the key: "args": [ {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, {"option": "Hex", "string": "1748e7179bd56570d51fa4ba287cc3e5"}, + 16, "ECB", "Hex", "Hex", {"option": "Hex", "string": ""}, - {"option": "Hex", "string": ""} + {"option": "Hex", "string": ""}, + "Off" + ] + } + ], + }, + { + name: "AES Decrypt: IV from input, with too short input", + input: "1748e7179bd56570d51fa4ba287cc3e5", + expectedOutput: "Input is too short to contain an IV of 16 bytes.", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 16, + "ECB", "Hex", "Hex", + {"option": "Hex", "string": ""}, + {"option": "Hex", "string": ""}, + "From start" + ] + } + ], + }, + { + name: "AES Decrypt: AES-256-ECB with IV from input start, Binary", + input: "1748e7179bd56570d51fa4ba287cc3e57e8521ba3f356ef692a51841807e141464aadc07bbc0ef2b628b8745bae356d245682a220688afca7be987b60cb120681ed42680ee93a67065619a3beaac11111a6cd88a6afa9e367722cb57df343f8548f2d691b295184da4ed5f3b763aaa8558502cb348ab58e81986337096e90caa", + expectedOutput: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 16, + "ECB", "Hex", "Hex", + {"option": "Hex", "string": ""}, + {"option": "Hex", "string": ""}, + "From start" + ] + } + ], + }, + { + name: "AES Decrypt: AES-256-ECB with IV from input end, Binary", + input: "7e8521ba3f356ef692a51841807e141464aadc07bbc0ef2b628b8745bae356d245682a220688afca7be987b60cb120681ed42680ee93a67065619a3beaac11111a6cd88a6afa9e367722cb57df343f8548f2d691b295184da4ed5f3b763aaa8558502cb348ab58e81986337096e90caa1748e7179bd56570d51fa4ba287cc3e5", + expectedOutput: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 16, + "ECB", "Hex", "Hex", + {"option": "Hex", "string": ""}, + {"option": "Hex", "string": ""}, + "From end" + ] + } + ], + }, + { + name: "AES Decrypt: AES-256-GCM with IV from input start, Binary, AAD", + input: "1748e7179bd56570d51fa4ba287cc3e51287f188ad4d7ab0d9ff69b3c29cb11f861389532d8cb9337181da2e8cfc74a84927e8c0dd7a28a32fd485afe694259a63c199b199b95edd87c7aa95329feac340f2b78b72956a85f367044d821766b1b7135815571df44900695f1518cf3ae38ecb650f", + expectedOutput: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 16, + "GCM", "Hex", "Hex", + {"option": "Hex", "string": "a8f04c4d93bbef82bef61a103371aef9"}, + {"option": "UTF8", "string": "additional data"}, + "From start" + ] + } + ], + }, + { + name: "AES Decrypt: AES-256-GCM with 12-byte IV from input start, Binary, AAD", + input: "1748e7179bd56570d51fa4ba623c81f4605da9ac3df29c67c43abe4aad5230dca82a98ab31f042fe871b81a0a1e8b8af41044d46f627828e7d11eca2d04ac27f4e7c7c9a20da87854df9868a2ddbd67d85f7db92f9ff1272cfb7955a2d279dbe715965011fddf6e730e79e7b22f89817", + expectedOutput: "7a0e643132750e96d805d11e9e48e281fa39a41039286423cc1c045e5442b40bf1c3f2822bded3f9c8ef11cb25da64dda9c7ab87c246bd305385150c98f31465c2a6180fe81d31ea289b916504d5a12e1de26cb10adba84a0cb0c86f94bc14bc554f3018", + recipeConfig: [ + { + "op": "AES Decrypt", + "args": [ + {"option": "Hex", "string": "2d767f6e9333d1c77581946e160b2b7368c2cdd5e2b80f04ca09d64e02afbfe1"}, + {"option": "Hex", "string": ""}, + 12, + "GCM", "Hex", "Hex", + {"option": "Hex", "string": "c311c9144f8ae145ec46e2c69179a4b7"}, + {"option": "UTF8", "string": "additional data"}, + "From start" ] } ], diff --git a/tests/operations/tests/Register.mjs b/tests/operations/tests/Register.mjs index 3ef7ef94..e455f0f8 100644 --- a/tests/operations/tests/Register.mjs +++ b/tests/operations/tests/Register.mjs @@ -59,6 +59,7 @@ TestRegister.addTests([ "option": "Hex", "string": "$R0" }, + 16, "CTR", "Hex", "Raw", { "option": "Hex", @@ -67,7 +68,8 @@ TestRegister.addTests([ { "option": "Hex", "string": "" - } + }, + "Off" ] } ] From c9298191890e46b77479a079523728f261e59653 Mon Sep 17 00:00:00 2001 From: Harel Katz <34490550+HarelKatz@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:44:20 +0300 Subject: [PATCH 10/13] feat: add Escape Smart Characters operation (#2391) --- src/core/config/Categories.json | 1 + src/core/operations/EscapeSmartCharacters.mjs | 129 +++++++++++++++++ tests/operations/index.mjs | 1 + .../tests/EscapeSmartCharacters.mjs | 132 ++++++++++++++++++ 4 files changed, 263 insertions(+) create mode 100644 src/core/operations/EscapeSmartCharacters.mjs create mode 100644 tests/operations/tests/EscapeSmartCharacters.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index dd6918dc..d3e7648a 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -49,6 +49,7 @@ "Escape Unicode Characters", "Unescape Unicode Characters", "Normalise Unicode", + "Escape Smart Characters", "To Quoted Printable", "From Quoted Printable", "To Punycode", diff --git a/src/core/operations/EscapeSmartCharacters.mjs b/src/core/operations/EscapeSmartCharacters.mjs new file mode 100644 index 00000000..39444e94 --- /dev/null +++ b/src/core/operations/EscapeSmartCharacters.mjs @@ -0,0 +1,129 @@ +/** + * @author HarelKatz [github.com/HarelKatz] + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * Escape Smart Characters operation + */ +class EscapeSmartCharacters extends Operation { + + /** + * EscapeSmartCharacters constructor + */ + constructor() { + super(); + + this.name = "Escape Smart Characters"; + this.module = "Default"; + this.description = "Converts smart (typographic) Unicode characters — e.g. smart quotes, em/en dashes, ellipses, ©, ®, ™, arrows — into their plain ASCII equivalents.

Characters with no ASCII mapping (e.g. ) are handled according to the 'Unmappable characters' option.

e.g. “Hello” — world… becomes \"Hello\" -- world..."; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Unmappable characters", + type: "option", + value: ["Include", "Remove", "Replace with '.'"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [unmappable] = args; + let result = ""; + for (const ch of input) { + if (ch.codePointAt(0) < 128) { + result += ch; + } else if (Object.prototype.hasOwnProperty.call(SMART_MAP, ch)) { + result += SMART_MAP[ch]; + } else { + switch (unmappable) { + case "Remove": + break; + case "Replace with '.'": + result += "."; + break; + case "Include": + default: + result += ch; + break; + } + } + } + return result; + } + +} + +const SMART_MAP = { + // Smart double quotes + "“": "\"", // “ left double quotation mark + "”": "\"", // ” right double quotation mark + "„": "\"", // „ double low-9 quotation mark + "‟": "\"", // ‟ double high-reversed-9 quotation mark + "″": "\"", // ″ double prime + + // Smart single quotes / apostrophes + "‘": "'", // ‘ left single quotation mark + "’": "'", // ’ right single quotation mark / apostrophe + "‚": "'", // ‚ single low-9 quotation mark + "‛": "'", // ‛ single high-reversed-9 quotation mark + "′": "'", // ′ prime + + // Dashes & hyphens + "‐": "-", // ‐ hyphen + "‑": "-", // ‑ non-breaking hyphen + "‒": "-", // ‒ figure dash + "–": "-", // – en dash + "—": "--", // — em dash + "―": "--", // ― horizontal bar + + // Ellipsis + "…": "...", // … + + // Trademark / copyright symbols + "©": "(c)", // © + "®": "(r)", // ® + "™": "(tm)", // ™ + + // Arrows + "←": "<--", // ← + "→": "-->", // → + "↑": "^", // ↑ + "↓": "v", // ↓ + "↔": "<->", // ↔ + "⇐": "<==", // ⇐ + "⇒": "==>", // ⇒ + "⇔": "<=>", // ⇔ + + // Guillemets + "«": "<<", // « + "»": ">>", // » + "‹": "<", // ‹ + "›": ">", // › + + // Math & misc symbols + "×": "x", // × + "÷": "/", // ÷ + "±": "+/-", // ± + "•": "*", // • + "·": ".", // · + + // Non-ASCII spaces + "\u00A0": " ", // NBSP + "\u2002": " ", // en space + "\u2003": " ", // em space + "\u2009": " ", // thin space + "\u200A": " " // hair space +}; + +export default EscapeSmartCharacters; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index c44270fd..44792560 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -69,6 +69,7 @@ import "./tests/DropNthBytes.mjs"; import "./tests/ECDSA.mjs"; import "./tests/ELFInfo.mjs"; import "./tests/Enigma.mjs"; +import "./tests/EscapeSmartCharacters.mjs"; import "./tests/ExtractAudioMetadata.mjs"; import "./tests/ExtractEmailAddresses.mjs"; import "./tests/ExtractHashes.mjs"; diff --git a/tests/operations/tests/EscapeSmartCharacters.mjs b/tests/operations/tests/EscapeSmartCharacters.mjs new file mode 100644 index 00000000..428c3ad8 --- /dev/null +++ b/tests/operations/tests/EscapeSmartCharacters.mjs @@ -0,0 +1,132 @@ +/** + * Escape Smart Characters tests + * + * @author HarelKatz [github.com/HarelKatz] + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + "name": "Escape Smart Characters: smart quotes and apostrophes", + "input": "“Hello,” she said, ‘yes.’", + "expectedOutput": "\"Hello,\" she said, 'yes.'", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: em dash, en dash and ellipsis", + "input": "page 1–3 — wait…", + "expectedOutput": "page 1-3 -- wait...", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: trademark symbols", + "input": "Foo© Bar® Baz™", + "expectedOutput": "Foo(c) Bar(r) Baz(tm)", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: arrows and guillemets", + "input": "← → ↔ ⇒ « »", + "expectedOutput": "<-- --> <-> ==> << >>", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: math and misc", + "input": "3 × 4 ÷ 2 = 6, ±0.5 • item", + "expectedOutput": "3 x 4 / 2 = 6, +/-0.5 * item", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: NBSP becomes regular space", + "input": "a b c", + "expectedOutput": "a b c", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: unmappable Include preserves char", + "input": "warning: ☣ hazard", + "expectedOutput": "warning: ☣ hazard", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: unmappable Remove drops char", + "input": "warning: ☣ hazard", + "expectedOutput": "warning: hazard", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Remove"] + } + ] + }, + { + "name": "Escape Smart Characters: unmappable Replace substitutes dot", + "input": "warning: ☣ hazard", + "expectedOutput": "warning: . hazard", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Replace with '.'"] + } + ] + }, + { + "name": "Escape Smart Characters: pure ASCII passes through", + "input": "hello world! 123", + "expectedOutput": "hello world! 123", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + }, + { + "name": "Escape Smart Characters: empty input", + "input": "", + "expectedOutput": "", + "recipeConfig": [ + { + "op": "Escape Smart Characters", + "args": ["Include"] + } + ] + } +]); From d735496641493725fbdf64f1c0064296c7f3fdac Mon Sep 17 00:00:00 2001 From: andreas Date: Fri, 5 Jun 2026 21:19:24 +0200 Subject: [PATCH 11/13] Update README to reflect AES Decrypt changes (#2502) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6da7d3ec..50b1a44d 100755 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ You can use as many operations as you like in simple or complex ways. Some examp - [Carry out different operations on data of different types][8] - [Use parts of the input as arguments to operations][9] - [Perform AES decryption, extracting the IV from the beginning of the cipher stream][10] + - [A simpler way to perform the same AES Decryption][13] - [Automagically detect several layers of nested encoding][12] @@ -147,6 +148,7 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice [7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA [8]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',false,'base64',10)To_Hex('Space')Return()Label('base64')To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA [9]: https://gchq.github.io/CyberChef/#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ - [10]: https://gchq.github.io/CyberChef/#recipe=Register('(.%7B32%7D)',true,false)Drop_bytes(0,32,false)AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D)&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg + [10]: https://gchq.github.io/CyberChef/#recipe=Register('(.%7B32%7D)',true,false,false)Drop_bytes(0,32,false)AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,16,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D,%7B'option':'Hex','string':''%7D,'Off')&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg [11]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'Standard',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4 [12]: https://gchq.github.io/CyberChef/#recipe=Magic(3,false,false)&input=V1VhZ3dzaWFlNm1QOGdOdENDTFVGcENwQ0IyNlJtQkRvREQ4UGFjZEFtekF6QlZqa0syUXN0RlhhS2hwQzZpVVM3UkhxWHJKdEZpc29SU2dvSjR3aGptMWFybTg2NHFhTnE0UmNmVW1MSHJjc0FhWmM1VFhDWWlmTmRnUzgzZ0RlZWpHWDQ2Z2FpTXl1QlY2RXNrSHQxc2NnSjg4eDJ0TlNvdFFEd2JHWTFtbUNvYjJBUkdGdkNLWU5xaU45aXBNcTFaVTFtZ2tkYk51R2NiNzZhUnRZV2hDR1VjOGc5M1VKdWRoYjhodHNoZVpud1RwZ3FoeDgzU1ZKU1pYTVhVakpUMnptcEM3dVhXdHVtcW9rYmRTaTg4WXRrV0RBYzFUb291aDJvSDRENGRkbU5LSldVRHBNd21uZ1VtSzE0eHdtb21jY1BRRTloTTE3MkFQblNxd3hkS1ExNzJSa2NBc3lzbm1qNWdHdFJtVk5OaDJzMzU5d3I2bVMyUVJQ + [13]: https://gchq.github.io/CyberChef/#recipe=AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,16,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D,%7B'option':'Hex','string':''%7D,'From%20start')&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg From 61deeb81653677b6f04fc01e1e8c4edd2104ca59 Mon Sep 17 00:00:00 2001 From: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:21:26 +0100 Subject: [PATCH 12/13] Npm and yarn/major version updates (#2527) Updated versions: * cspell 10.0.1 * grunt-eslint 26.0.0 * grunt-webpack 8.0.0 * bignumber.js 11.1.2 * cbor 10.0.12 * diff 9.0.0 * protobufjs 8.5.0 * tesseract.js 7.0.0 * ua-parser-js 2.0.10 --- package-lock.json | 720 +++++++++++++------------ package.json | 18 +- src/core/operations/ParseUserAgent.mjs | 2 +- tests/browser/02_ops.js | 8 +- 4 files changed, 393 insertions(+), 355 deletions(-) diff --git a/package-lock.json b/package-lock.json index 623c8440..12be0199 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "assert": "^2.1.0", "avsc": "^5.7.9", "bcryptjs": "^3.0.3", - "bignumber.js": "^9.3.1", + "bignumber.js": "^11.1.2", "blakejs": "^1.2.1", "bootstrap": "4.6.2", "bootstrap-colorpicker": "^3.4.0", @@ -29,7 +29,7 @@ "browserify-zlib": "^0.2.0", "bson": "^7.2.0", "buffer": "^6.0.3", - "cbor": "9.0.2", + "cbor": "10.0.12", "chi-squared": "^1.1.0", "codepage": "^1.15.0", "crypto-api": "^0.8.5", @@ -38,7 +38,7 @@ "ctph.js": "0.0.5", "d3": "7.9.0", "d3-hexbin": "^0.2.2", - "diff": "^5.2.2", + "diff": "^9.0.0", "dompurify": "^3.4.7", "es6-promisify": "^7.0.0", "escodegen": "^2.1.0", @@ -85,7 +85,7 @@ "path": "^0.12.7", "popper.js": "^1.16.1", "process": "^0.11.10", - "protobufjs": "^7.6.2", + "protobufjs": "^8.5.0", "punycode.js": "^2.3.1", "qr-image": "^3.2.0", "reflect-metadata": "^0.2.2", @@ -97,8 +97,8 @@ "sql-formatter": "^15.8.0", "ssdeep.js": "0.0.3", "stream-browserify": "^3.0.0", - "tesseract.js": "^6.0.1", - "ua-parser-js": "^1.0.41", + "tesseract.js": "^7.0.0", + "ua-parser-js": "^2.0.10", "unorm": "^1.6.0", "url": "^0.11.4", "utf8": "^3.0.0", @@ -129,7 +129,7 @@ "compression-webpack-plugin": "^12.0.0", "copy-webpack-plugin": "^14.0.0", "core-js": "^3.49.0", - "cspell": "^9.7.0", + "cspell": "^10.0.1", "css-loader": "^7.1.4", "eslint": "^9.39.4", "eslint-plugin-jsdoc": "^50.8.0", @@ -141,9 +141,9 @@ "grunt-contrib-connect": "^5.0.1", "grunt-contrib-copy": "~1.0.0", "grunt-contrib-watch": "^1.1.0", - "grunt-eslint": "^25.0.0", + "grunt-eslint": "^26.0.0", "grunt-exec": "~3.0.0", - "grunt-webpack": "^6.0.0", + "grunt-webpack": "^8.0.0", "grunt-zip": "^1.0.0", "html-webpack-plugin": "^5.6.7", "imports-loader": "^5.0.0", @@ -1921,9 +1921,9 @@ } }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.8.0.tgz", - "integrity": "sha512-MpXFpVyBPfJQ1YuVotljqUaGf6lWuf+fuWBBgs0PHFYTSjRPWuIxviAaCDnup/CJLLH60xQL4IlcQe4TOjzljw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-10.0.1.tgz", + "integrity": "sha512-WvkSDNX4Uyyj/ZgbPO6L38iFNMfK1EqsH1FteRiI2qLz6QZMXRFrIt12OqiWIplzZDDaVpBH9FCJOPJll0fjCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1988,86 +1988,86 @@ "@cspell/dict-zig": "^1.0.0" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/cspell-json-reporter": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.8.0.tgz", - "integrity": "sha512-nqUaSo9T7l8KrE22gc7ZIs+zvP7ak1i7JqGdRs8sGvh2Ijqj43qYQLePgb1b/vm8a1bavnc51m+vf05hpd3g3Q==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-10.0.1.tgz", + "integrity": "sha512-/nes1RGILec3WCBcoMOd0byNTBtnJuPaVz/+ZzqYkLtY7x58VMcBG5kyP6hPyN8cIwjRADE/SR43gwdXuqk/FA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.8.0" + "@cspell/cspell-types": "10.0.1" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/cspell-performance-monitor": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-performance-monitor/-/cspell-performance-monitor-9.8.0.tgz", - "integrity": "sha512-IsrXYzn23yJICIQ915ACdf+2lNEcFNTu5BIQt3khHOsGVvZ9/AZYpu9Dk825vUyZG7RHg2Oi6dYNiJtULG4ouQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-performance-monitor/-/cspell-performance-monitor-10.0.1.tgz", + "integrity": "sha512-9tVcHXwRnbazUv4WSG0h3MqV4+LgmLNgSALAQUflPPW0EMxTf7C4Dmv9cgxJyCEQrdnVKCr58nPPaahhz9LJUg==", "dev": true, "license": "MIT", "engines": { - "node": ">=20.18" + "node": ">=22.18.0" } }, "node_modules/@cspell/cspell-pipe": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.8.0.tgz", - "integrity": "sha512-ISEUD8PHYkd2Ktafc6hFfIXdGKYUvthA09NbwwZsWmOqYyk4wWKHZKqyyxD+BcrFwOyMOJcD8OEvIjkRQp2SJw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-10.0.1.tgz", + "integrity": "sha512-HPeXMD9AZ3V/qPkvQaPcak+C7cJ2z7JTHN8smd6J8L2aThLRky2cHc2OyeaHPSHB7WA47b4z2n5u5nawZhv5VQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/cspell-resolver": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.8.0.tgz", - "integrity": "sha512-PZJj56BZpKfMxOzWkyt7b+aIXObe+8Ku/zLI4xDXPSuQPENbHBFHfPIZx68CyGEkanKxZ1ewKVx/FT1FUy+wDA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-10.0.1.tgz", + "integrity": "sha512-PIzkZHD1fGUQx1XteK2d1iQ0Mzq/maYcoB4jkvAiiR6WqP3MWYNKFdI9z+R5pOq5KgMfW+5Ig1q0oSR6h8irlA==", "dev": true, "license": "MIT", "dependencies": { "global-directory": "^5.0.0" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/cspell-service-bus": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.8.0.tgz", - "integrity": "sha512-P45sd2nqwcqhulBBbQnZB/JNcobecTrP4Ky3vmEq0cprsvavc+ZoHF9U2Ql5ghMSUzjrF2n1aNzZ8cH4IlsnKg==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-10.0.1.tgz", + "integrity": "sha512-y6NcIGP2IdXaBL4PVH8vxsr7K27wzz3Ech87UtUtrDSXAiVEOvXgAIknEOUVp59rTlUE8Rn4IRURC6f/hgMyfw==", "dev": true, "license": "MIT", "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/cspell-types": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.8.0.tgz", - "integrity": "sha512-7Ge4UD6SCA49Tcc3+GTlz3Xn4cqVUAXtDO0u9IeHvJgkN3Me2Rw2GB/CtGmhKST3YeEeZMX7ww09TdHMUJlehw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-10.0.1.tgz", + "integrity": "sha512-kLgLShnWADDVreKC63pBrWkcvxgZzFIfO34Jhx/SWfuOIA3cD8AXT+HjyuLfoGJ7mUb58hv2kUziKzEy4INb1w==", "dev": true, "license": "MIT", "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/cspell-worker": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-worker/-/cspell-worker-9.8.0.tgz", - "integrity": "sha512-W8FLdE3MXPLbWtAXciILQhk9CHd6Mt+HRjZHM8m+dwE1Bc2TAjUai8kIxsdhHUq58p7gYY2ekr5sg1uYOUgTAA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-worker/-/cspell-worker-10.0.1.tgz", + "integrity": "sha512-L2bJerfuYOls2wEknm8FmynLtj/G7O4UqX9I/HznRggEW6i2yZIxagDetpVDNowpyavNHJ3SJtUFiyMiZc16Sw==", "dev": true, "license": "MIT", "dependencies": { - "cspell-lib": "9.8.0" + "cspell-lib": "10.0.1" }, "engines": { - "node": ">=20.18" + "node": ">=22.18.0" } }, "node_modules/@cspell/dict-ada": { @@ -2092,13 +2092,13 @@ "license": "MIT" }, "node_modules/@cspell/dict-bash": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.2.2.tgz", - "integrity": "sha512-kyWbwtX3TsCf5l49gGQIZkRLaB/P8g73GDRm41Zu8Mv51kjl2H7Au0TsEvHv7jzcsRLS6aUYaZv6Zsvk1fOz+Q==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.2.3.tgz", + "integrity": "sha512-ljUZoKHbDqw5Sx0qpL2qTUlmkmr+vhZH/sCNrNaBZKTbdgiswErSnIF1jRbGmEitJNxHRHWsuZyVgnTGfVO1Yw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-shell": "1.1.2" + "@cspell/dict-shell": "1.2.0" } }, "node_modules/@cspell/dict-companies": { @@ -2130,9 +2130,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-css": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.1.1.tgz", - "integrity": "sha512-y/Vgo6qY08e1t9OqR56qjoFLBCpi4QfWMf2qzD1l9omRZwvSMQGRPz4x0bxkkkU4oocMAeztjzCsmLew//c/8w==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.1.2.tgz", + "integrity": "sha512-+ylGoKdwZ2sVOCOnU2Eq5wDZx+RaVX3HoKyNHGGsFvhSw6IidQ6tH/mAPKBDofViHJoWCPNlklE0lTr6MDG3QA==", "dev": true, "license": "MIT" }, @@ -2144,9 +2144,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-data-science": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.13.tgz", - "integrity": "sha512-l1HMEhBJkPmw4I2YGVu2eBSKM89K9pVF+N6qIr5Uo5H3O979jVodtuwP8I7LyPrJnC6nz28oxeGRCLh9xC5CVA==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.14.tgz", + "integrity": "sha512-jl6Ds4u5u5JT+yY30pWQpAbdCHfy3lCcNkLbpL/AZKoUaLEoXbaYsps9xQtvD7DyaiXxiLZkdH2yHHXtoFtZyg==", "dev": true, "license": "MIT" }, @@ -2179,9 +2179,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-en_us": { - "version": "4.4.33", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.33.tgz", - "integrity": "sha512-zWftVqfUStDA37wO1ZNDN1qMJOfcxELa8ucHW8W8wBAZY3TK5Nb6deLogCK/IJi/Qljf30dwwuqqv84Qqle9Tw==", + "version": "4.4.35", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.35.tgz", + "integrity": "sha512-xWpxBCc/FzzMMo/A+0qwARVaIIhR0Ql8yhhv4rvsvg+GfQF+LG9yzg2GwTM5N2rjvzmM3nKuR9zxFZq2I6fJSg==", "dev": true, "license": "MIT" }, @@ -2193,9 +2193,9 @@ "license": "CC BY-SA 4.0" }, "node_modules/@cspell/dict-en-gb-mit": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.22.tgz", - "integrity": "sha512-xE5Vg6gGdMkZ1Ep6z9SJMMioGkkT1GbxS5Mm0U3Ey1/H68P0G7cJcyiVr1CARxFbLqKE4QUpoV1o6jz1Z5Yl9Q==", + "version": "3.1.24", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.24.tgz", + "integrity": "sha512-Oowb/Uzkh7OmDRdCcETzMc9imEb4IpLlHJXoYjX8A8DS2X/54gqSjI915JFB8hKtFjBko5OM0BLQ+6cZhFEMmQ==", "dev": true, "license": "MIT" }, @@ -2340,13 +2340,13 @@ "license": "MIT" }, "node_modules/@cspell/dict-markdown": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.16.tgz", - "integrity": "sha512-976RRqKv6cwhrxdFCQP2DdnBVB86BF57oQtPHy4Zbf4jF/i2Oy29MCrxirnOBalS1W6KQeto7NdfDXRAwkK4PQ==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.17.tgz", + "integrity": "sha512-H8bAxih6U8NOnSPL7R8My+tqjaB4tmnJTjERuz4zYqmf+cH+5xshX3UVgKlwWFcyjsYfv/zEDuRdMctQv1q6HQ==", "dev": true, "license": "MIT", "peerDependencies": { - "@cspell/dict-css": "^4.1.1", + "@cspell/dict-css": "^4.1.2", "@cspell/dict-html": "^4.0.15", "@cspell/dict-html-symbol-entities": "^4.0.5", "@cspell/dict-typescript": "^3.2.3" @@ -2367,9 +2367,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-npm": { - "version": "5.2.38", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.38.tgz", - "integrity": "sha512-21ucGRPYYhr91C2cDBoMPTrcIOStQv33xOqJB0JLoC5LAs2Sfj9EoPGhGb+gIFVHz6Ia7JQWE2SJsOVFJD1wmg==", + "version": "5.2.41", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.41.tgz", + "integrity": "sha512-To3xsfRmMBYVXtWVEdUgV35M9a/JZ54dSuoY6m6D3uHKKL3I326Wmy4xifZ3PU8MQaWhyEH7zbIcUEtKwTQMcA==", "dev": true, "license": "MIT" }, @@ -2395,13 +2395,13 @@ "license": "MIT" }, "node_modules/@cspell/dict-python": { - "version": "4.2.26", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.26.tgz", - "integrity": "sha512-hbjN6BjlSgZOG2dA2DtvYNGBM5Aq0i0dHaZjMOI9K/9vRicVvKbcCiBSSrR3b+jwjhQL5ff7HwG5xFaaci0GQA==", + "version": "4.2.27", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.27.tgz", + "integrity": "sha512-Rj6xQgYS4X6ienjgAZF+njA0GRY4oSPouJWv0vfikCTn6EWlfk0V6Dy1HP3Migj1O+IC2NmespgVq+BZNSp8OA==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/dict-data-science": "^2.0.13" + "@cspell/dict-data-science": "^2.0.14" } }, "node_modules/@cspell/dict-r": { @@ -2433,9 +2433,9 @@ "license": "MIT" }, "node_modules/@cspell/dict-shell": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-shell/-/dict-shell-1.1.2.tgz", - "integrity": "sha512-WqOUvnwcHK1X61wAfwyXq04cn7KYyskg90j4lLg3sGGKMW9Sq13hs91pqrjC44Q+lQLgCobrTkMDw9Wyl9nRFA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-shell/-/dict-shell-1.2.0.tgz", + "integrity": "sha512-PVctvT22lJ49niMiakO8xieY7ELCAzjSqhejWR7bAMb5AZ9F4WDEs+XdGMnoVHWeXq7K5rcepLPmEJb+37zzIw==", "dev": true, "license": "MIT" }, @@ -2496,57 +2496,57 @@ "license": "MIT" }, "node_modules/@cspell/dynamic-import": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.8.0.tgz", - "integrity": "sha512-wMgb32lqG9g6lCipUQsY9Bk5idXPDz7wvzOqEsU1M2HmNYmdE1wfPoRpfQfsVL965iG3+6h8QLr2+8FKpweFEQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-10.0.1.tgz", + "integrity": "sha512-mP1gdq00aIcH8HxNMqnH11X6BKxLcneDtFgl/ecjIKnaGKwi44m8AndP5Kr4ODaYdl8UUw9O3dJh7KaQXnLHZQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.8.0", + "@cspell/url": "10.0.1", "import-meta-resolve": "^4.2.0" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/filetypes": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.8.0.tgz", - "integrity": "sha512-yHvtYn9qt6zykua77sNzTcf7HrG/dpo/+2pCMGSrfSrQypSNT6FUFvMS04W7kwhP86U1GkCjppNykXuoH3cqug==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-10.0.1.tgz", + "integrity": "sha512-Z5S35giU5IW49fBBq6BksUbE8PC4IYPfaKuwl5Nl9jkf/OkAKiBmCowKX45NzRUQInwK/GSqqIUifrNeI6LdLw==", "dev": true, "license": "MIT", "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/rpc": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/rpc/-/rpc-9.8.0.tgz", - "integrity": "sha512-t4lHEa254W+PePXNQ1noW7QhQxz/mhsJ9X8LEt0ILzBbPWCJzN+JuaM7EiolIPiwxtfxpMwKx9482kt4eTja7A==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/rpc/-/rpc-10.0.1.tgz", + "integrity": "sha512-axSRKv3zEAmBm66iD/FV/MPmE4/Yf7c3PZiwTW894Yd3iEhtn3KPKeTrqQ2/tDrhB1Z2qTsap/Hue0MK4o5WXg==", "dev": true, "license": "MIT", "engines": { - "node": ">=20.18" + "node": ">=22.18.0" } }, "node_modules/@cspell/strong-weak-map": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.8.0.tgz", - "integrity": "sha512-HocksAqZ0JcWA5oWO7TIlOCftXVGkPGzbeFlCRRrjJpZmYQH+4NdeEXyQC6T89NGocp45td/CgyBcAaFMy1N9w==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-10.0.1.tgz", + "integrity": "sha512-lenN1DVyPi8nJLSMSJJ670ddTjyiruLueuSZO1qLcxBqUhgxDt/mALu9N/1m6WdOVcg6m/5cLiZVg2KOo2UzRw==", "dev": true, "license": "MIT", "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@cspell/url": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.8.0.tgz", - "integrity": "sha512-LY1lFiZLTQF/ma1ilfKmRmFmEOw0RfYhyl0UMhY7/d93b+kiDMhxP/9Qir4+5LyiRncaE3++ZcWno9Hya+ssRg==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-10.0.1.tgz", + "integrity": "sha512-abYYgI29wJhWIfWTYrYuzRYDcHQUQ1N5ylnhxYn1NJnIQMqUWGLbDmt12JABtZ+R6h6UNatQrS7rhP86etvJyQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/@csstools/color-helpers": { @@ -4416,69 +4416,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", - "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", - "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", - "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", - "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", - "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", - "license": "BSD-3-Clause" - }, "node_modules/@puppeteer/browsers": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.4.tgz", @@ -4698,6 +4635,7 @@ "version": "25.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.18.0" @@ -5856,13 +5794,10 @@ } }, "node_modules/bignumber.js": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", - "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", - "license": "MIT", - "engines": { - "node": "*" - } + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-11.1.2.tgz", + "integrity": "sha512-9idDyC15Vpk+53w4OfxEu2PqHSKFQUffrH1oTvnkJ9fduTJ032tpuI2sxS04oCzocklokWUZmWVEkTEQdLmUOQ==", + "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", @@ -6560,15 +6495,15 @@ "license": "CC-BY-4.0" }, "node_modules/cbor": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", - "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "version": "10.0.12", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-10.0.12.tgz", + "integrity": "sha512-exQDevYd7ZQLP4moMQcZkKCVZsXLAtUSflObr3xTh4xzFIv/xBCdvCd6L259kQOUP2kcTC0jvC6PpZIf/WmRXA==", "license": "MIT", "dependencies": { - "nofilter": "^3.1.0" + "nofilter": "^3.0.2" }, "engines": { - "node": ">=16" + "node": ">=20" } }, "node_modules/chai-nightwatch": { @@ -6737,23 +6672,6 @@ "node": ">= 10.0" } }, - "node_modules/clear-module": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz", - "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^2.0.0", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cli-boxes": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", @@ -6844,6 +6762,21 @@ "node": ">=0.8" } }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/codepage": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", @@ -6914,9 +6847,9 @@ } }, "node_modules/comment-json": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.6.2.tgz", - "integrity": "sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-5.0.0.tgz", + "integrity": "sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==", "dev": true, "license": "MIT", "dependencies": { @@ -7449,188 +7382,200 @@ "license": "MIT" }, "node_modules/cspell": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.8.0.tgz", - "integrity": "sha512-qL0VErMSn8BDxaPxcV+9uenffgjPS+5Jfz+m4rCsvYjzLwr7AaaJBWWSV2UiAe/4cturae8n8qzxiGnbbazkRw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-10.0.1.tgz", + "integrity": "sha512-Gg6w/flT3fKfl3la62hfTnhtNnDQ+9mU7kUhVqw/axl/Ms4oENw0oJMkWFIoj4f6nL/SDPz7KcPXd2XbkKFNmQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-json-reporter": "9.8.0", - "@cspell/cspell-performance-monitor": "9.8.0", - "@cspell/cspell-pipe": "9.8.0", - "@cspell/cspell-types": "9.8.0", - "@cspell/cspell-worker": "9.8.0", - "@cspell/dynamic-import": "9.8.0", - "@cspell/url": "9.8.0", + "@cspell/cspell-json-reporter": "10.0.1", + "@cspell/cspell-performance-monitor": "10.0.1", + "@cspell/cspell-pipe": "10.0.1", + "@cspell/cspell-types": "10.0.1", + "@cspell/cspell-worker": "10.0.1", + "@cspell/dynamic-import": "10.0.1", + "@cspell/url": "10.0.1", "ansi-regex": "^6.2.2", "chalk": "^5.6.2", "chalk-template": "^1.1.2", "commander": "^14.0.3", - "cspell-config-lib": "9.8.0", - "cspell-dictionary": "9.8.0", - "cspell-gitignore": "9.8.0", - "cspell-glob": "9.8.0", - "cspell-io": "9.8.0", - "cspell-lib": "9.8.0", + "cspell-config-lib": "10.0.1", + "cspell-dictionary": "10.0.1", + "cspell-gitignore": "10.0.1", + "cspell-glob": "10.0.1", + "cspell-io": "10.0.1", + "cspell-lib": "10.0.1", "fast-json-stable-stringify": "^2.1.0", "flatted": "^3.4.2", - "semver": "^7.7.4", - "tinyglobby": "^0.2.15" + "semver": "^7.8.1", + "tinyglobby": "^0.2.16" }, "bin": { "cspell": "bin.mjs", "cspell-esm": "bin.mjs" }, "engines": { - "node": ">=20.18" + "node": ">=22.18.0" }, "funding": { "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" } }, "node_modules/cspell-config-lib": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.8.0.tgz", - "integrity": "sha512-gMJBAgYPvvO+uDFLUcGWaTu6/e+r8mm4GD4rQfWa/yV4F9fj+yOYLIMZqLWRvT1moHZX1FxyVvUbJcmZ1gfebg==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-10.0.1.tgz", + "integrity": "sha512-hMpo/0j6k7pbiqrLDOLJKD2IGP9XwhjKf2miiM6p84Xeo4nyuFZaxxDCQ68R851HSYFrrdltgpoipMbj1h2Tnw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-types": "9.8.0", - "comment-json": "^4.6.2", + "@cspell/cspell-types": "10.0.1", + "comment-json": "^5.0.0", "smol-toml": "^1.6.1", - "yaml": "^2.8.3" + "yaml": "^2.9.0" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/cspell-dictionary": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.8.0.tgz", - "integrity": "sha512-QW4hdkWcrxZA1QNqi26U0S/U3/V+tKCm7JaaesEJW2F6Ao+23AbHVwidyAVtXaEhGkn6PxB+epKrrAa6nE69qA==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-10.0.1.tgz", + "integrity": "sha512-3cZ659vgsZWkzGQJR/sNqGDVt/OnvTSieLKI76V++4t1bHJfochb9ZrrwsuMsb1VPGiyqClUP1/O6WrefF/FVg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-performance-monitor": "9.8.0", - "@cspell/cspell-pipe": "9.8.0", - "@cspell/cspell-types": "9.8.0", - "cspell-trie-lib": "9.8.0", + "@cspell/cspell-performance-monitor": "10.0.1", + "@cspell/cspell-pipe": "10.0.1", + "@cspell/cspell-types": "10.0.1", + "cspell-trie-lib": "10.0.1", "fast-equals": "^6.0.0" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/cspell-gitignore": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.8.0.tgz", - "integrity": "sha512-SDUa1DmSfT20+JH7XtyzcEL9KfurneoR/XbmlrtPQZP/LUHXh3yz4x/0vFIkEFXNWdSckY0QdWTz8DaxClCf4Q==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-10.0.1.tgz", + "integrity": "sha512-wN23U61Mx6qPJN3CesOmBU9vnbJ0jQm/ylK0iaVui3CcnO7Zzl5qLu5mPHUzGQGm8yso6qjyxqo16Ho7LpZGOQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.8.0", - "cspell-glob": "9.8.0", - "cspell-io": "9.8.0" + "@cspell/url": "10.0.1", + "cspell-glob": "10.0.1", + "cspell-io": "10.0.1" }, "bin": { "cspell-gitignore": "bin.mjs" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/cspell-glob": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.8.0.tgz", - "integrity": "sha512-Uvj/iHXs+jpsJyIEnhEoJTWXb1GVyZ9T05L5JFtZfsQNXrh8SRDQPscjxbg4okKr63N7WevfioQum/snHNYvmw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-10.0.1.tgz", + "integrity": "sha512-7bII9J3aSSpZDwhx7w+zfQXbMxHZQ3be0ilUp5bHrsjz6o07v/NqOHMGcwKdPn1sw2dxDz9sv057xE5pqXnSdw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/url": "9.8.0", + "@cspell/url": "10.0.1", "picomatch": "^4.0.4" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/cspell-grammar": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.8.0.tgz", - "integrity": "sha512-01XMq2vhPS0Gvxnfed9uvOwH+3cXddHYxW0PwCE+SZdcC6TN8yM6glByuLt1qFustAmQVE5GSr7uAY9o4pZQRg==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-10.0.1.tgz", + "integrity": "sha512-xC9AFYmaI9wsO//a7S5tdDGKGJVD5UEEsTg+Up2fi7lPfXIryisYmV6tePNL1SEg0idYss4ja8LUZ3Mib09BjQ==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-pipe": "9.8.0", - "@cspell/cspell-types": "9.8.0" + "@cspell/cspell-pipe": "10.0.1", + "@cspell/cspell-types": "10.0.1" }, "bin": { "cspell-grammar": "bin.mjs" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/cspell-io": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.8.0.tgz", - "integrity": "sha512-JINaEWQEzR4f2upwdZOFcft+nBvQgizJfrOLszxG3p+BIzljnGklqE/nUtLFZpBu0oMJvuM/Fd+GsWor0yP7Xw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-10.0.1.tgz", + "integrity": "sha512-8C2ka07faxflnaqEBO3pektS21XViE/SEHT7F5ZD1ou7FyMR5u3xawTBJSczClfsxLt/WYeztBYrpmGAjmjksw==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-service-bus": "9.8.0", - "@cspell/url": "9.8.0" + "@cspell/cspell-service-bus": "10.0.1", + "@cspell/url": "10.0.1" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, "node_modules/cspell-lib": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.8.0.tgz", - "integrity": "sha512-G2TtPcye5QE5ev3YgWq42UOJLpTZ6naO/47oIm+jmeSYbgnbcOSThnEE7uMycx+TTNOz/vJVFpZmQyt0bWCftw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-10.0.1.tgz", + "integrity": "sha512-RpsIPiLzc4/YMW8BMRKpyJ81x439qjYWcqgdKeXnMkbKM88J9PexzutfFf/4v97v96KzfNitEzMpbI0uj8OeUg==", "dev": true, "license": "MIT", "dependencies": { - "@cspell/cspell-bundled-dicts": "9.8.0", - "@cspell/cspell-performance-monitor": "9.8.0", - "@cspell/cspell-pipe": "9.8.0", - "@cspell/cspell-resolver": "9.8.0", - "@cspell/cspell-types": "9.8.0", - "@cspell/dynamic-import": "9.8.0", - "@cspell/filetypes": "9.8.0", - "@cspell/rpc": "9.8.0", - "@cspell/strong-weak-map": "9.8.0", - "@cspell/url": "9.8.0", - "clear-module": "^4.1.2", - "cspell-config-lib": "9.8.0", - "cspell-dictionary": "9.8.0", - "cspell-glob": "9.8.0", - "cspell-grammar": "9.8.0", - "cspell-io": "9.8.0", - "cspell-trie-lib": "9.8.0", + "@cspell/cspell-bundled-dicts": "10.0.1", + "@cspell/cspell-performance-monitor": "10.0.1", + "@cspell/cspell-pipe": "10.0.1", + "@cspell/cspell-resolver": "10.0.1", + "@cspell/cspell-types": "10.0.1", + "@cspell/dynamic-import": "10.0.1", + "@cspell/filetypes": "10.0.1", + "@cspell/rpc": "10.0.1", + "@cspell/strong-weak-map": "10.0.1", + "@cspell/url": "10.0.1", + "cspell-config-lib": "10.0.1", + "cspell-dictionary": "10.0.1", + "cspell-glob": "10.0.1", + "cspell-grammar": "10.0.1", + "cspell-io": "10.0.1", + "cspell-trie-lib": "10.0.1", "env-paths": "^4.0.0", "gensequence": "^8.0.8", - "import-fresh": "^3.3.1", + "import-fresh": "^4.0.0", "resolve-from": "^5.0.0", "vscode-languageserver-textdocument": "^1.0.12", "vscode-uri": "^3.1.0", "xdg-basedir": "^5.1.0" }, "engines": { - "node": ">=20" + "node": ">=22.18.0" } }, - "node_modules/cspell-trie-lib": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.8.0.tgz", - "integrity": "sha512-GXIyqxya8QLp6SjKsAN9w3apvt1Ww7GKcZvTBaP76OfLoyb1QC6unwmObY2cZs1manCntGwHrgU6vFNuXnTzpw==", + "node_modules/cspell-lib/node_modules/import-fresh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-4.0.0.tgz", + "integrity": "sha512-Fpi660c7VPDM3fPKYovStd9IP1CPOikf6v/dGxJJMmHPcwYQIMJ4W7kO1avBYEpMqkCh+Dx3Ln6H7VYqgztLjw==", "dev": true, "license": "MIT", "engines": { - "node": ">=20" + "node": ">=22.15" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cspell-trie-lib": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-10.0.1.tgz", + "integrity": "sha512-BFvhalSkRQFjKrZ//FKK7fRGrZFpifnxB5AwCkzsIsBZqicsfafcQ1xP21qpb0QqyV/IomjNgviG+tRJs+0rMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.18.0" }, "peerDependencies": { - "@cspell/cspell-types": "9.8.0" + "@cspell/cspell-types": "10.0.1" } }, "node_modules/cspell/node_modules/ansi-regex": { @@ -7647,9 +7592,9 @@ } }, "node_modules/cspell/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", "dev": true, "license": "ISC", "bin": { @@ -8479,6 +8424,26 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-europe-js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/detect-europe-js/-/detect-europe-js-0.1.2.tgz", + "integrity": "sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -8511,9 +8476,9 @@ "license": "Apache-2.0" }, "node_modules/diff": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", - "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", + "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -10572,17 +10537,17 @@ } }, "node_modules/grunt-eslint": { - "version": "25.0.0", - "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-25.0.0.tgz", - "integrity": "sha512-JIV5IPgOuacorFLmYtUTq0n+0qGIL9FSQJ4KVnNfCg/8Fm+K1t6OWrzXXI8TxWTwq2K9E3parFVXCpn1sGLbKQ==", + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-26.0.0.tgz", + "integrity": "sha512-HP/Mu00nBtdLDk0i1V1gLplYBgce4nBjxwmtpo3Eit/h5OUzGxEsgBxprkT4I5bN1x79w6wDnrN+7CX29OZatg==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.2", - "eslint": "^9.0.0" + "eslint": "^9.22.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10742,21 +10707,17 @@ } }, "node_modules/grunt-webpack": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/grunt-webpack/-/grunt-webpack-6.0.0.tgz", - "integrity": "sha512-FtRVTGJGuV9Ic/OrCR80p5u601e0ekvTyHo7vnwVo3XlvRh5wR1ATAVT9FnnobHqZnQ/DeF84W97si5+roUWEA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/grunt-webpack/-/grunt-webpack-8.0.0.tgz", + "integrity": "sha512-pcDVu1DPcDaEik29MDwMPuYwYCYW2Xhoze9UjWGGVJLK7XR/dpQ6kCwT3IDqByrVhDwobtKqFtk3b7l75OiJcw==", "dev": true, "license": "MIT", "dependencies": { "deep-for-each": "^3.0.0", - "lodash": "^4.17.21" + "webpack-merge": "^6.0.1" }, "engines": { - "node": ">=16.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": "^22.13.0 || >=24" }, "peerDependencies": { "webpack": "^5.0.0" @@ -11995,6 +11956,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-standalone-pwa": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz", + "integrity": "sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, "node_modules/is-string": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", @@ -13323,6 +13304,16 @@ "balanced-match": "^1.0.0" } }, + "node_modules/mocha/node_modules/diff": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/mocha/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -14392,19 +14383,6 @@ "tslib": "^2.0.3" } }, - "node_modules/parent-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz", - "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/parse-asn1": { "version": "5.1.9", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", @@ -15108,23 +15086,12 @@ "license": "MIT" }, "node_modules/protobufjs": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.2.tgz", - "integrity": "sha512-N9EiLovGEQOJSPF26Ij7qUGvahfEnq0eeYZ02aigIedkmz1qZSwjnP9SBITHJuF/6MYbIW4HDN8zdYjsjqJKXQ==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.5.0.tgz", + "integrity": "sha512-df1jWDPA5VIBNRtuAHjqr09f2qN5D4Vke1wYqOQg1XJ7ZDpA7BD6L7E4tyChgGRLB5hqk2m79Zsy0WHwV9a84A==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.5", - "@protobufjs/eventemitter": "^1.1.1", - "@protobufjs/fetch": "^1.1.1", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.2", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.1", - "@types/node": ">=13.7.0", "long": "^5.3.2" }, "engines": { @@ -16369,6 +16336,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -17202,9 +17182,9 @@ "license": "MIT" }, "node_modules/tesseract.js": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-6.0.1.tgz", - "integrity": "sha512-/sPvMvrCtgxnNRCjbTYbr7BRu0yfWDsMZQ2a/T5aN/L1t8wUQN6tTWv6p6FwzpoEBA0jrN2UD2SX4QQFRdoDbA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-7.0.0.tgz", + "integrity": "sha512-exPBkd+z+wM1BuMkx/Bjv43OeLBxhL5kKWsz/9JY+DXcXdiBjiAch0V49QR3oAJqCaL5qURE0vx9Eo+G5YE7mA==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -17214,15 +17194,15 @@ "node-fetch": "^2.6.9", "opencollective-postinstall": "^2.0.3", "regenerator-runtime": "^0.13.3", - "tesseract.js-core": "^6.0.0", - "wasm-feature-detect": "^1.2.11", + "tesseract.js-core": "^7.0.0", + "wasm-feature-detect": "^1.8.0", "zlibjs": "^0.3.1" } }, "node_modules/tesseract.js-core": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-6.1.2.tgz", - "integrity": "sha512-pv4GjmramjdObhDyR1q85Td8X60Puu/lGQn7Kw2id05LLgHhAcWgnz6xSdMCSxBMWjQDmMyDXPTC2aqADdpiow==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-7.0.0.tgz", + "integrity": "sha512-WnNH518NzmbSq9zgTPeoF8c+xmilS8rFIl1YKbk/ptuuc7p6cLNELNuPAzcmsYw450ca6bLa8j3t0VAtq435Vw==", "license": "Apache-2.0" }, "node_modules/thingies": { @@ -17292,14 +17272,14 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -17562,10 +17542,30 @@ "node": ">= 0.4" } }, + "node_modules/ua-is-frozen": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz", + "integrity": "sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT" + }, "node_modules/ua-parser-js": { - "version": "1.0.41", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", - "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-2.0.10.tgz", + "integrity": "sha512-t+3Ktbq0Ies2vaSezfOaWiolH4OigQIO1dk+1xDpOydB1COVPocVYOrEV5rqZ0kFY9XYG1v9LutCyMgYBpABcw==", "funding": [ { "type": "opencollective", @@ -17580,7 +17580,12 @@ "url": "https://github.com/sponsors/faisalman" } ], - "license": "MIT", + "license": "AGPL-3.0-or-later", + "dependencies": { + "detect-europe-js": "^0.1.2", + "is-standalone-pwa": "^0.1.1", + "ua-is-frozen": "^0.1.2" + }, "bin": { "ua-parser-js": "script/cli.js" }, @@ -17640,6 +17645,7 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -18209,6 +18215,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/webpack-merge/node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, "node_modules/webpack-node-externals": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", @@ -18391,6 +18422,13 @@ "node": ">=8" } }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/winston": { "version": "2.4.7", "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", @@ -18708,9 +18746,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 8a82b685..e8c648cb 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "compression-webpack-plugin": "^12.0.0", "copy-webpack-plugin": "^14.0.0", "core-js": "^3.49.0", - "cspell": "^9.7.0", + "cspell": "^10.0.1", "css-loader": "^7.1.4", "eslint": "^9.39.4", "eslint-plugin-jsdoc": "^50.8.0", @@ -71,9 +71,9 @@ "grunt-contrib-connect": "^5.0.1", "grunt-contrib-copy": "~1.0.0", "grunt-contrib-watch": "^1.1.0", - "grunt-eslint": "^25.0.0", + "grunt-eslint": "^26.0.0", "grunt-exec": "~3.0.0", - "grunt-webpack": "^6.0.0", + "grunt-webpack": "^8.0.0", "grunt-zip": "^1.0.0", "html-webpack-plugin": "^5.6.7", "imports-loader": "^5.0.0", @@ -105,7 +105,7 @@ "assert": "^2.1.0", "avsc": "^5.7.9", "bcryptjs": "^3.0.3", - "bignumber.js": "^9.3.1", + "bignumber.js": "^11.1.2", "blakejs": "^1.2.1", "bootstrap": "4.6.2", "bootstrap-colorpicker": "^3.4.0", @@ -113,7 +113,7 @@ "browserify-zlib": "^0.2.0", "bson": "^7.2.0", "buffer": "^6.0.3", - "cbor": "9.0.2", + "cbor": "10.0.12", "chi-squared": "^1.1.0", "codepage": "^1.15.0", "crypto-api": "^0.8.5", @@ -122,7 +122,7 @@ "ctph.js": "0.0.5", "d3": "7.9.0", "d3-hexbin": "^0.2.2", - "diff": "^5.2.2", + "diff": "^9.0.0", "dompurify": "^3.4.7", "es6-promisify": "^7.0.0", "escodegen": "^2.1.0", @@ -169,7 +169,7 @@ "path": "^0.12.7", "popper.js": "^1.16.1", "process": "^0.11.10", - "protobufjs": "^7.6.2", + "protobufjs": "^8.5.0", "punycode.js": "^2.3.1", "qr-image": "^3.2.0", "reflect-metadata": "^0.2.2", @@ -181,8 +181,8 @@ "sql-formatter": "^15.8.0", "ssdeep.js": "0.0.3", "stream-browserify": "^3.0.0", - "tesseract.js": "^6.0.1", - "ua-parser-js": "^1.0.41", + "tesseract.js": "^7.0.0", + "ua-parser-js": "^2.0.10", "unorm": "^1.6.0", "url": "^0.11.4", "utf8": "^3.0.0", diff --git a/src/core/operations/ParseUserAgent.mjs b/src/core/operations/ParseUserAgent.mjs index 57ac9312..5a2f2a96 100644 --- a/src/core/operations/ParseUserAgent.mjs +++ b/src/core/operations/ParseUserAgent.mjs @@ -5,7 +5,7 @@ */ import Operation from "../Operation.mjs"; -import UAParser from "ua-parser-js"; +import { UAParser } from "ua-parser-js"; /** * Parse User Agent operation diff --git a/tests/browser/02_ops.js b/tests/browser/02_ops.js index 32bd14d6..e295f08c 100644 --- a/tests/browser/02_ops.js +++ b/tests/browser/02_ops.js @@ -80,8 +80,8 @@ module.exports = { testOpHtml(browser, "Bombe", "XTSYN WAEUG EZALY NRQIM AMLZX MFUOD AWXLY LZCUZ QOQBQ JLCPK NDDRW F", "table tr:last-child td:first-child", "ECG", ["3-rotor", "LEYJVCNIXWPBQMDRTAKZGFUHOS", "BDFHJLCPRTXVZNYEIWGAKMUSQO Date: Tue, 9 Jun 2026 09:36:07 +0100 Subject: [PATCH 13/13] New operation improvements (#1431) Co-authored-by: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> --- .gitignore | 1 + src/core/config/scripts/generateOpsIndex.mjs | 63 ++++++ src/core/config/scripts/newOperation.mjs | 35 ++- tests/operations/index.mjs | 217 ------------------- tests/operations/tests/FlaskSession.mjs | 19 +- tests/operations/tests/IPv6Transition.mjs | 8 +- tests/operations/tests/ParseX509CRL.mjs | 32 +-- 7 files changed, 126 insertions(+), 249 deletions(-) delete mode 100644 tests/operations/index.mjs diff --git a/.gitignore b/.gitignore index 157558e9..a1e9dab6 100755 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ src/core/config/OperationConfig.json src/core/operations/index.mjs src/node/config/OperationConfig.json src/node/index.mjs +tests/operations/index.mjs **/*.DS_Store tests/browser/output/* .node-version diff --git a/src/core/config/scripts/generateOpsIndex.mjs b/src/core/config/scripts/generateOpsIndex.mjs index d8dd6a70..ccf3da7b 100644 --- a/src/core/config/scripts/generateOpsIndex.mjs +++ b/src/core/config/scripts/generateOpsIndex.mjs @@ -58,3 +58,66 @@ fs.writeFileSync( code ); console.log("Written operation index."); + +// find all test files +const testsDir = path.join(process.cwd() + "/tests/operations/tests/"); +const testObjs = []; +fs.readdirSync(testsDir).forEach(file => { + if (!file.endsWith(".mjs")) return; + testObjs.push(file.split(".mjs")[0]); +}); + +// Construct test index file +code = `/** +* THIS FILE IS AUTOMATICALLY GENERATED BY src/core/config/scripts/generateOpsIndex.mjs +* +* @author john [john19696@protonmail.com] +* @author tlwr [toby@toby.codes] +* @author n1474335 [n1474335@gmail.com] +* @copyright Crown Copyright ${new Date().getUTCFullYear()} +* @license Apache-2.0 +*/ + +import { + setLongTestFailure, + logTestReport, +} from "../lib/utils.mjs"; + +import "../lib/wasmFetchPolyfill.mjs"; + +import TestRegister from "../lib/TestRegister.mjs"; +`; + +testObjs.forEach(obj => { + if (obj !== "SplitColourChannels") + code += `import "./tests/${obj}.mjs";\n`; + else + code += `// Cannot test operations that use the File type yet +// import "./tests/SplitColourChannels.mjs";\n`; +}); + +code += ` + +const testStatus = { + allTestsPassing: true, + counts: { + total: 0, + } +}; + +setLongTestFailure(); + +const logOpsTestReport = logTestReport.bind(null, testStatus); + +(async function() { + const results = await TestRegister.runTests(); + logOpsTestReport(results); +})(); +`; + +// Write tests file +fs.writeFileSync( + path.join(testsDir, "../index.mjs"), + code +); +console.log("Written operation tests index."); diff --git a/src/core/config/scripts/newOperation.mjs b/src/core/config/scripts/newOperation.mjs index 1686f6eb..e46dffcc 100644 --- a/src/core/config/scripts/newOperation.mjs +++ b/src/core/config/scripts/newOperation.mjs @@ -23,7 +23,7 @@ if (!fs.existsSync(dir)) { console.log("Example> node --experimental-modules src/core/config/scripts/newOperation.mjs"); process.exit(1); } - +const testDir = path.join(process.cwd() + "/tests/operations/tests/"); const ioTypes = ["string", "byteArray", "number", "html", "ArrayBuffer", "BigNumber", "JSON", "File", "List"]; const schema = { @@ -123,6 +123,30 @@ prompt.get(schema, (err, result) => { return txt.charAt(0).toUpperCase() + txt.substr(1); }).replace(/[\s-()./]/g, ""); + const testTemplate = `/** +* ${moduleName} tests +* +* @author ${result.authorName} [${result.authorEmail}] +* @copyright Crown Copyright ${(new Date()).getFullYear()} +* @license Apache-2.0 +*/ + +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "${result.opName}: test", + input: "Example input", + expectedOutput: "Expected output", + recipeConfig: [ + { + op: "${result.opName}", + args: [], + }, + ], + }, +]); +`; const template = `/** * @author ${result.authorName} [${result.authorEmail}] @@ -218,13 +242,16 @@ export default ${moduleName}; } fs.writeFileSync(filename, template); + const testFilename = path.join(testDir, `./${moduleName}.mjs`); + fs.writeFileSync(testFilename, testTemplate); + console.log(`\nOperation template written to ${colors.green(filename)}`); + console.log(`\nOperation test template written to ${colors.green(testFilename)}`); console.log(`\nNext steps: 1. Add your operation to ${colors.green("src/core/config/Categories.json")} -2. Write your operation code. -3. Write tests in ${colors.green("tests/operations/tests/")} +2. Write your operation code in ${colors.green(filename)} +3. Write your operation test code in ${colors.green(testFilename)} 4. Run ${colors.cyan("npm run lint")} and ${colors.cyan("npm run test")} 5. Submit a Pull Request to get your operation added to the official CyberChef repository.`); }); - diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs deleted file mode 100644 index 44792560..00000000 --- a/tests/operations/index.mjs +++ /dev/null @@ -1,217 +0,0 @@ -/* eslint no-console: 0 */ - -/** - * Test Runner - * - * For running the tests in the test register. - * - * @author tlwr [toby@toby.codes] - * @author n1474335 [n1474335@gmail.com] - * @copyright Crown Copyright 2017 - * @license Apache-2.0 - */ - -import "../lib/wasmFetchPolyfill.mjs"; -import { setLongTestFailure, logTestReport } from "../lib/utils.mjs"; - -import TestRegister from "../lib/TestRegister.mjs"; -import "./tests/A1Z26CipherDecode.mjs"; -import "./tests/AESKeyWrap.mjs"; -import "./tests/AnalyseUUID.mjs"; -import "./tests/AlternatingCaps.mjs"; -import "./tests/AvroToJSON.mjs"; -import "./tests/BaconCipher.mjs"; -import "./tests/Base32.mjs"; -import "./tests/Base45.mjs"; -import "./tests/Base58.mjs"; -import "./tests/Base62.mjs"; -import "./tests/Base64.mjs"; -import "./tests/Base85.mjs"; -import "./tests/Base92.mjs"; -import "./tests/BCD.mjs"; -import "./tests/Bech32.mjs"; -import "./tests/BitwiseOp.mjs"; -import "./tests/BLAKE2b.mjs"; -import "./tests/BLAKE2s.mjs"; -import "./tests/BLAKE3.mjs"; -import "./tests/Bombe.mjs"; -import "./tests/BSON.mjs"; -import "./tests/ByteRepr.mjs"; -import "./tests/CaesarBoxCipher.mjs"; -import "./tests/CaretMdecode.mjs"; -import "./tests/CartesianProduct.mjs"; -import "./tests/CBORDecode.mjs"; -import "./tests/CBOREncode.mjs"; -import "./tests/CetaceanCipherDecode.mjs"; -import "./tests/CetaceanCipherEncode.mjs"; -import "./tests/ChaCha.mjs"; -import "./tests/ChangeIPFormat.mjs"; -import "./tests/CharEnc.mjs"; -import "./tests/Charts.mjs"; -import "./tests/Ciphers.mjs"; -import "./tests/CipherSaber2.mjs"; -import "./tests/CMAC.mjs"; -import "./tests/Code.mjs"; -import "./tests/Colossus.mjs"; -import "./tests/Comment.mjs"; -import "./tests/Compress.mjs"; -import "./tests/ConditionalJump.mjs"; -import "./tests/ConvertCoordinateFormat.mjs"; -import "./tests/ConvertLeetSpeak.mjs"; -import "./tests/ConvertToNATOAlphabet.mjs"; -import "./tests/CRCChecksum.mjs"; -import "./tests/Crypt.mjs"; -import "./tests/CSV.mjs"; -import "./tests/DateTime.mjs"; -import "./tests/DefangIP.mjs"; -import "./tests/DisassembleARM.mjs"; -import "./tests/DropNthBytes.mjs"; -import "./tests/ECDSA.mjs"; -import "./tests/ELFInfo.mjs"; -import "./tests/Enigma.mjs"; -import "./tests/EscapeSmartCharacters.mjs"; -import "./tests/ExtractAudioMetadata.mjs"; -import "./tests/ExtractEmailAddresses.mjs"; -import "./tests/ExtractHashes.mjs"; -import "./tests/ExtractIPAddresses.mjs"; -import "./tests/Fernet.mjs"; -import "./tests/Float.mjs"; -import "./tests/FileTree.mjs"; -import "./tests/FletcherChecksum.mjs"; -import "./tests/Fork.mjs"; -import "./tests/FromDecimal.mjs"; -import "./tests/GenerateAllChecksums.mjs"; -import "./tests/GenerateAllHashes.mjs"; -import "./tests/GenerateDeBruijnSequence.mjs"; -import "./tests/GenerateQRCode.mjs"; -import "./tests/GetAllCasings.mjs"; -import "./tests/GOST.mjs"; -import "./tests/Gunzip.mjs"; -import "./tests/Gzip.mjs"; -import "./tests/Hash.mjs"; -import "./tests/HASSH.mjs"; -import "./tests/HaversineDistance.mjs"; -import "./tests/Hex.mjs"; -import "./tests/Hexdump.mjs"; -import "./tests/HKDF.mjs"; -import "./tests/Image.mjs"; -import "./tests/IndexOfCoincidence.mjs"; -import "./tests/JA3Fingerprint.mjs"; -import "./tests/JA4.mjs"; -import "./tests/JA3SFingerprint.mjs"; -import "./tests/Jsonata.mjs"; -import "./tests/JSONBeautify.mjs"; -import "./tests/JSONMinify.mjs"; -import "./tests/JSONtoCSV.mjs"; -import "./tests/Jump.mjs"; -import "./tests/JWK.mjs"; -import "./tests/JWTDecode.mjs"; -import "./tests/JWTSign.mjs"; -import "./tests/JWTVerify.mjs"; -import "./tests/LevenshteinDistance.mjs"; -import "./tests/Lorenz.mjs"; -import "./tests/LS47.mjs"; -import "./tests/LuhnChecksum.mjs"; -import "./tests/LZNT1Decompress.mjs"; -import "./tests/LZString.mjs"; -import "./tests/Magic.mjs"; -import "./tests/Media.mjs"; -import "./tests/MIMEDecoding.mjs"; -import "./tests/Modhex.mjs"; -import "./tests/MorseCode.mjs"; -import "./tests/MS.mjs"; -import "./tests/MultipleBombe.mjs"; -import "./tests/MurmurHash3.mjs"; -import "./tests/NetBIOS.mjs"; -import "./tests/NormaliseUnicode.mjs"; -import "./tests/NTLM.mjs"; -import "./tests/OTP.mjs"; -import "./tests/ParseEthernetFrame.mjs"; -import "./tests/ParseIPv4Header.mjs"; -import "./tests/ParseIPRange.mjs"; -import "./tests/ParseObjectIDTimestamp.mjs"; -import "./tests/ParseQRCode.mjs"; -import "./tests/ParseSSHHostKey.mjs"; -import "./tests/ParseTCP.mjs"; -import "./tests/ParseTLSRecord.mjs"; -import "./tests/ParseTLV.mjs"; -import "./tests/ParseUDP.mjs"; -import "./tests/PEMtoHex.mjs"; -import "./tests/PGP.mjs"; -import "./tests/PHP.mjs"; -import "./tests/ParityBit.mjs"; -import "./tests/PHPSerialize.mjs"; -import "./tests/PowerSet.mjs"; -import "./tests/Protobuf.mjs"; -import "./tests/PubKeyFromCert.mjs"; -import "./tests/PubKeyFromPrivKey.mjs"; -import "./tests/Rabbit.mjs"; -import "./tests/RAKE.mjs"; -import "./tests/Regex.mjs"; -import "./tests/Register.mjs"; -import "./tests/RemoveANSIEscapeCodes.mjs"; -import "./tests/RegularExpression.mjs"; -import "./tests/RenderMarkdown.mjs"; -import "./tests/RisonEncodeDecode.mjs"; -import "./tests/Rotate.mjs"; -import "./tests/RSA.mjs"; -import "./tests/Salsa20.mjs"; -import "./tests/XSalsa20.mjs"; -import "./tests/SeqUtils.mjs"; -import "./tests/SetDifference.mjs"; -import "./tests/SetIntersection.mjs"; -import "./tests/SetUnion.mjs"; -import "./tests/Shuffle.mjs"; -import "./tests/SIGABA.mjs"; -import "./tests/SM2.mjs"; -import "./tests/SM4.mjs"; -import "./tests/RC6.mjs"; -// import "./tests/SplitColourChannels.mjs"; // Cannot test operations that use the File type yet -import "./tests/SQLBeautify.mjs"; -import "./tests/StrUtils.mjs"; -import "./tests/StripIPv4Header.mjs"; -import "./tests/StripTCPHeader.mjs"; -import "./tests/StripUDPHeader.mjs"; -import "./tests/Subsection.mjs"; -import "./tests/SwapCase.mjs"; -import "./tests/SymmetricDifference.mjs"; -import "./tests/TakeNthBytes.mjs"; -import "./tests/Template.mjs"; -import "./tests/TextEncodingBruteForce.mjs"; -import "./tests/TextIntegerConverter.mjs"; -import "./tests/ToFromInsensitiveRegex.mjs"; -import "./tests/TranslateDateTimeFormat.mjs"; -import "./tests/Typex.mjs"; -import "./tests/UnescapeString.mjs"; -import "./tests/Unicode.mjs"; -import "./tests/Wrap.mjs"; -import "./tests/URLEncodeDecode.mjs"; -import "./tests/RSA.mjs"; -import "./tests/CBOREncode.mjs"; -import "./tests/CBORDecode.mjs"; -import "./tests/JA3Fingerprint.mjs"; -import "./tests/JA3SFingerprint.mjs"; -import "./tests/HASSH.mjs"; -import "./tests/JSONtoYAML.mjs"; - -// Cannot test operations that use the File type yet -// import "./tests/SplitColourChannels.mjs"; -import "./tests/YARA.mjs"; -import "./tests/ParseCSR.mjs"; -import "./tests/XXTEA.mjs"; - -const testStatus = { - allTestsPassing: true, - counts: { - total: 0, - }, -}; - -setLongTestFailure(); - -const logOpsTestReport = logTestReport.bind(null, testStatus); - -(async function () { - const results = await TestRegister.runTests(); - logOpsTestReport(results); -})(); diff --git a/tests/operations/tests/FlaskSession.mjs b/tests/operations/tests/FlaskSession.mjs index 7becf400..427f5f1e 100644 --- a/tests/operations/tests/FlaskSession.mjs +++ b/tests/operations/tests/FlaskSession.mjs @@ -14,15 +14,18 @@ const validTokenSha256 = "eyJyb2xlIjoic3VwZXJ1c2VyIiwidXNlciI6ImFkbWluIn0.aab3Ew const validKey = "mysecretkey"; const wrongKey = "notTheKey"; -const outputObject = { - user: "admin", - role: "superuser", -}; +const outputObject = `{ + "role": "superuser", + "user": "admin" +}`; -const outputVerify = { - valid: true, - payload: outputObject, -}; +const outputVerify = `{ + "valid": true, + "payload": { + "role": "superuser", + "user": "admin" + } +}`; TestRegister.addTests([ { diff --git a/tests/operations/tests/IPv6Transition.mjs b/tests/operations/tests/IPv6Transition.mjs index f7558c31..75aabefe 100644 --- a/tests/operations/tests/IPv6Transition.mjs +++ b/tests/operations/tests/IPv6Transition.mjs @@ -12,7 +12,7 @@ TestRegister.addTests([ { name: "IPv6 Transition: IPv4 to IPv6", input: "198.51.100.7", - expectedOutput: "6to4: 2002:c633:6407::/48\nIPv4 Mapped: ::ffff:c633:6407\nIPv4 Translated: ::ffff:0:c633:6407\nNat 64: 64:ff9b::c633:6407", + expectedOutput: "6to4: 2002:c633:6407::/48\nIPv4 Mapped: ::ffff:c633:6407\nIPv4 Translated: ::ffff:0:c633:6407\nNat 64: 64:ff9b::c633:6407\n", recipeConfig: [ { op: "IPv6 Transition Addresses", @@ -22,7 +22,7 @@ TestRegister.addTests([ }, { name: "IPv6 Transition: IPv4 /24 Range to IPv6", input: "198.51.100.0/24", - expectedOutput: "6to4: 2002:c633:6400::/40\nIPv4 Mapped: ::ffff:c633:6400/120\nIPv4 Translated: ::ffff:0:c633:6400/120\nNat 64: 64:ff9b::c633:6400/120", + expectedOutput: "6to4: 2002:c633:6400::/40\nIPv4 Mapped: ::ffff:c633:6400/120\nIPv4 Translated: ::ffff:0:c633:6400/120\nNat 64: 64:ff9b::c633:6400/120\n", recipeConfig: [ { op: "IPv6 Transition Addresses", @@ -32,7 +32,7 @@ TestRegister.addTests([ }, { name: "IPv6 Transition: IPv4 to IPv6 Remove headers", input: "198.51.100.7", - expectedOutput: "2002:c633:6407::/48\n::ffff:c633:6407\n::ffff:0:c633:6407\n64:ff9b::c633:6407", + expectedOutput: "2002:c633:6407::/48\n::ffff:c633:6407\n::ffff:0:c633:6407\n64:ff9b::c633:6407\n", recipeConfig: [ { op: "IPv6 Transition Addresses", @@ -42,7 +42,7 @@ TestRegister.addTests([ }, { name: "IPv6 Transition: IPv6 to IPv4", input: "64:ff9b::c633:6407", - expectedOutput: "IPv4: 198.51.100.7", + expectedOutput: "IPv4: 198.51.100.7\n", recipeConfig: [ { op: "IPv6 Transition Addresses", diff --git a/tests/operations/tests/ParseX509CRL.mjs b/tests/operations/tests/ParseX509CRL.mjs index 33de5e38..a889a498 100644 --- a/tests/operations/tests/ParseX509CRL.mjs +++ b/tests/operations/tests/ParseX509CRL.mjs @@ -51,16 +51,16 @@ const OUT_CRL_PEM_RSA = `Certificate Revocation List (CRL): DirName:/C=UK/ST=London/O=BB/CN=Test Root CA serial:37:5D:4B:F6:BD:7C:11:7C:CC:46:1A:FF:D7:2F:2C:26:F8:1E:4B:3D X509v3 CRL Distribution Points: - Full Name: - URI:http://example.com/full-crl - Full Name: - URI:ldap://example.com/full-crl - Full Name: - IP:127.0.0.1 + Full Name: + URI:http://example.com/full-crl + Full Name: + URI:ldap://example.com/full-crl + Full Name: + IP:127.0.0.1 X509v3 CRL Number: 1E3C - issuerAltName: - Unsupported CRL extension. Try openssl CLI. + X509v3 Issuer Alternative Name: + Revoked Certificates: Serial Number: 1000 Revocation Date: Sun, 25 Aug 2024 03:23:08 GMT @@ -143,16 +143,16 @@ const OUT_CRL_PEM_RSA_CRL_REASON_AND_INVALIDITY_DATE = `Certificate Revocation L DirName:/C=UK/ST=London/O=BB/CN=Test Root CA serial:37:5D:4B:F6:BD:7C:11:7C:CC:46:1A:FF:D7:2F:2C:26:F8:1E:4B:3D X509v3 CRL Distribution Points: - Full Name: - URI:http://example.com/full-crl - Full Name: - URI:ldap://example.com/full-crl - Full Name: - IP:127.0.0.1 + Full Name: + URI:http://example.com/full-crl + Full Name: + URI:ldap://example.com/full-crl + Full Name: + IP:127.0.0.1 X509v3 CRL Number: 1E3D - issuerAltName: - Unsupported CRL extension. Try openssl CLI. + X509v3 Issuer Alternative Name: + Revoked Certificates: Serial Number: 1000 Revocation Date: Sun, 25 Aug 2024 12:08:48 GMT