From f0468d391d974b046e4b2757f09d2c9a79667107 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sat, 20 Jun 2026 09:21:07 +0200 Subject: [PATCH 01/19] fix Median operation returns incorrect result for unsorted odd-length inputs (#2284) --- src/core/lib/Arithmetic.mjs | 13 +++++++----- tests/operations/tests/Median.mjs | 33 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 tests/operations/tests/Median.mjs diff --git a/src/core/lib/Arithmetic.mjs b/src/core/lib/Arithmetic.mjs index 7c10855f..5fbc5771 100644 --- a/src/core/lib/Arithmetic.mjs +++ b/src/core/lib/Arithmetic.mjs @@ -108,14 +108,17 @@ export function mean(data) { * @returns {BigNumber} */ export function median(data) { - if ((data.length % 2) === 0 && data.length > 0) { + if (data.length > 0) { data.sort(function(a, b) { return a.minus(b); }); - const first = data[Math.floor(data.length / 2)]; - const second = data[Math.floor(data.length / 2) - 1]; - return mean([first, second]); - } else { + + if ((data.length % 2) === 0) { + const first = data[Math.floor(data.length / 2)]; + const second = data[Math.floor(data.length / 2) - 1]; + return mean([first, second]); + } + return data[Math.floor(data.length / 2)]; } } diff --git a/tests/operations/tests/Median.mjs b/tests/operations/tests/Median.mjs new file mode 100644 index 00000000..555f2edd --- /dev/null +++ b/tests/operations/tests/Median.mjs @@ -0,0 +1,33 @@ +/** + * Median operation tests. + * + * @author copilot-swe-agent[bot] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Median: odd-length input", + input: "10 1 2", + expectedOutput: "2", + recipeConfig: [ + { + op: "Median", + args: ["Space"], + }, + ], + }, + { + name: "Median: even-length input", + input: "10 1 2 5", + expectedOutput: "3.5", + recipeConfig: [ + { + op: "Median", + args: ["Space"], + }, + ], + }, +]); From 0fd6190b4676142f56e0c11a05a14e1a95af1e4f Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sat, 20 Jun 2026 09:48:49 +0200 Subject: [PATCH 02/19] fix: From Base operation produces wrong results for fractional inputs (#2285) Co-authored-by: Claude Opus 4.6 --- src/core/operations/FromBase.mjs | 3 +- tests/operations/tests/FromBase.mjs | 66 +++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/operations/tests/FromBase.mjs diff --git a/src/core/operations/FromBase.mjs b/src/core/operations/FromBase.mjs index 4abd5c44..8e69153b 100644 --- a/src/core/operations/FromBase.mjs +++ b/src/core/operations/FromBase.mjs @@ -51,9 +51,10 @@ class FromBase extends Operation { if (number.length === 1) return result; // Fractional part + const radixBN = new BigNumber(radix); for (let i = 0; i < number[1].length; i++) { const digit = new BigNumber(number[1][i], radix); - result += digit.div(Math.pow(radix, i+1)); + result = result.plus(digit.div(radixBN.pow(i + 1))); } return result; diff --git a/tests/operations/tests/FromBase.mjs b/tests/operations/tests/FromBase.mjs new file mode 100644 index 00000000..9f89a1f9 --- /dev/null +++ b/tests/operations/tests/FromBase.mjs @@ -0,0 +1,66 @@ +/** + * From Base operation tests. + * + * @author Willi Ballenthin + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "From Base: binary integer", + input: "1010", + expectedOutput: "10", + recipeConfig: [ + { + op: "From Base", + args: [2], + }, + ], + }, + { + name: "From Base: binary fraction", + input: "10.1", + expectedOutput: "2.5", + recipeConfig: [ + { + op: "From Base", + args: [2], + }, + ], + }, + { + name: "From Base: hex fraction", + input: "a.8", + expectedOutput: "10.5", + recipeConfig: [ + { + op: "From Base", + args: [16], + }, + ], + }, + { + name: "From Base: octal integer", + input: "77", + expectedOutput: "63", + recipeConfig: [ + { + op: "From Base", + args: [8], + }, + ], + }, + { + name: "From Base: octal fraction", + input: "7.4", + expectedOutput: "7.5", + recipeConfig: [ + { + op: "From Base", + args: [8], + }, + ], + }, +]); From 5a2eeed06680080e0a29c31ce3740740b840f0fe Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sat, 20 Jun 2026 09:52:56 +0200 Subject: [PATCH 03/19] fix Set Difference and Set Intersection preserve duplicates from first sample (#2286) --- src/core/operations/SetDifference.mjs | 9 +++++++- src/core/operations/SetIntersection.mjs | 9 +++++++- tests/operations/tests/SetDifference.mjs | 22 ++++++++++++++++++++ tests/operations/tests/SetIntersection.mjs | 24 +++++++++++++++++++++- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/core/operations/SetDifference.mjs b/src/core/operations/SetDifference.mjs index dc46c079..d5ab92d3 100644 --- a/src/core/operations/SetDifference.mjs +++ b/src/core/operations/SetDifference.mjs @@ -75,9 +75,16 @@ class SetDifference extends Operation { * @returns {Object[]} */ runSetDifference(a, b) { + const excluded = new Set(b); + const seen = new Set(); + return a .filter((item) => { - return b.indexOf(item) === -1; + if (excluded.has(item) || seen.has(item)) { + return false; + } + seen.add(item); + return true; }) .join(this.itemDelimiter); } diff --git a/src/core/operations/SetIntersection.mjs b/src/core/operations/SetIntersection.mjs index 7e6dbe10..423fcd4f 100644 --- a/src/core/operations/SetIntersection.mjs +++ b/src/core/operations/SetIntersection.mjs @@ -75,9 +75,16 @@ class SetIntersection extends Operation { * @returns {Object[]} */ runIntersect(a, b) { + const included = new Set(b); + const seen = new Set(); + return a .filter((item) => { - return b.indexOf(item) > -1; + if (!included.has(item) || seen.has(item)) { + return false; + } + seen.add(item); + return true; }) .join(this.itemDelimiter); } diff --git a/tests/operations/tests/SetDifference.mjs b/tests/operations/tests/SetDifference.mjs index 40fac524..5836cb36 100644 --- a/tests/operations/tests/SetDifference.mjs +++ b/tests/operations/tests/SetDifference.mjs @@ -53,4 +53,26 @@ TestRegister.addTests([ }, ], }, + { + name: "Set Difference: duplicates in first set are removed", + input: "red,red,blue\n\nblue", + expectedOutput: "red", + recipeConfig: [ + { + op: "Set Difference", + args: ["\n\n", ","], + }, + ], + }, + { + name: "Set Difference: duplicates in both sets", + input: "1 1 2 2 3\n\n2 2 3 3", + expectedOutput: "1", + recipeConfig: [ + { + op: "Set Difference", + args: ["\n\n", " "], + }, + ], + }, ]); diff --git a/tests/operations/tests/SetIntersection.mjs b/tests/operations/tests/SetIntersection.mjs index c9146c01..a638db4a 100644 --- a/tests/operations/tests/SetIntersection.mjs +++ b/tests/operations/tests/SetIntersection.mjs @@ -52,5 +52,27 @@ TestRegister.addTests([ args: ["z", "-"], }, ], - } + }, + { + name: "Set Intersection: duplicates in first set are removed", + input: "red,red,blue\n\nred,blue", + expectedOutput: "red,blue", + recipeConfig: [ + { + op: "Set Intersection", + args: ["\n\n", ","], + }, + ], + }, + { + name: "Set Intersection: duplicates in both sets", + input: "1 1 2 2 3\n\n2 2 3 3 4", + expectedOutput: "2 3", + recipeConfig: [ + { + op: "Set Intersection", + args: ["\n\n", " "], + }, + ], + }, ]); From 9a8a279b826f066916a3673c78cb39c79f13175f Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sat, 20 Jun 2026 09:56:09 +0200 Subject: [PATCH 04/19] fix: Unescape Unicode Characters accepts 4-6 hex digits for U+ prefix (#2287) --- .../operations/UnescapeUnicodeCharacters.mjs | 3 +- .../tests/UnescapeUnicodeCharacters.mjs | 88 +++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 tests/operations/tests/UnescapeUnicodeCharacters.mjs diff --git a/src/core/operations/UnescapeUnicodeCharacters.mjs b/src/core/operations/UnescapeUnicodeCharacters.mjs index 02d16662..f7759c78 100644 --- a/src/core/operations/UnescapeUnicodeCharacters.mjs +++ b/src/core/operations/UnescapeUnicodeCharacters.mjs @@ -56,7 +56,8 @@ class UnescapeUnicodeCharacters extends Operation { */ run(input, args) { const prefix = prefixToRegex[args[0]], - regex = new RegExp(prefix+"([a-f\\d]{4})", "ig"); + quantifier = args[0] === "U+" ? "{4,6}" : "{4}", + regex = new RegExp(prefix+"([a-f\\d]"+quantifier+")", "ig"); let output = "", m, i = 0; diff --git a/tests/operations/tests/UnescapeUnicodeCharacters.mjs b/tests/operations/tests/UnescapeUnicodeCharacters.mjs new file mode 100644 index 00000000..99955e04 --- /dev/null +++ b/tests/operations/tests/UnescapeUnicodeCharacters.mjs @@ -0,0 +1,88 @@ +/** + * Unescape Unicode Characters operation tests. + * + * @author williballenthin + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Unescape Unicode Characters: \\u 4-digit BMP", + input: "\\u03c3\\u03bf\\u03c5", + expectedOutput: "σου", + recipeConfig: [ + { + op: "Unescape Unicode Characters", + args: ["\\u"], + }, + ], + }, + { + name: "Unescape Unicode Characters: %u 4-digit BMP", + input: "%u03c3%u03bf%u03c5", + expectedOutput: "σου", + recipeConfig: [ + { + op: "Unescape Unicode Characters", + args: ["%u"], + }, + ], + }, + { + name: "Unescape Unicode Characters: U+ 4-digit BMP", + input: "U+0041", + expectedOutput: "A", + recipeConfig: [ + { + op: "Unescape Unicode Characters", + args: ["U+"], + }, + ], + }, + { + name: "Unescape Unicode Characters: U+ 5-digit astral plane emoji", + input: "U+1F600", + expectedOutput: "\u{1F600}", + recipeConfig: [ + { + op: "Unescape Unicode Characters", + args: ["U+"], + }, + ], + }, + { + name: "Unescape Unicode Characters: U+ 6-digit zero-padded", + input: "U+000041", + expectedOutput: "A", + recipeConfig: [ + { + op: "Unescape Unicode Characters", + args: ["U+"], + }, + ], + }, + { + name: "Unescape Unicode Characters: U+ mixed lengths", + input: "U+0041 U+1F600 U+000042", + expectedOutput: "A \u{1F600} B", + recipeConfig: [ + { + op: "Unescape Unicode Characters", + args: ["U+"], + }, + ], + }, + { + name: "Unescape Unicode Characters: passthrough with no matches", + input: "hello world", + expectedOutput: "hello world", + recipeConfig: [ + { + op: "Unescape Unicode Characters", + args: ["\\u"], + }, + ], + }, +]); From 0a0d95bcbd7fece2004b77b540f2d3089f171b46 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sat, 20 Jun 2026 09:59:30 +0200 Subject: [PATCH 05/19] fix TLV Parser BER long-form length parsing (#2289) --- src/core/lib/TLVParser.mjs | 23 +++++++++++----- tests/operations/tests/ParseTLV.mjs | 41 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/core/lib/TLVParser.mjs b/src/core/lib/TLVParser.mjs index cb8432c1..1afd052e 100644 --- a/src/core/lib/TLVParser.mjs +++ b/src/core/lib/TLVParser.mjs @@ -33,20 +33,29 @@ export default class TLVParser { * @returns {number} */ getLength() { + let bytesInLength = this.bytesInLength; + let bigEndian = false; + if (this.basicEncodingRules) { - const bit = this.input[this.location]; - if (bit & 0x80) { - this.bytesInLength = bit & ~0x80; + const firstLengthByte = this.input[this.location]; + this.location++; + + if (firstLengthByte & 0x80) { + bytesInLength = firstLengthByte & ~0x80; + bigEndian = true; } else { - this.location++; - return bit & ~0x80; + return firstLengthByte & ~0x80; } } let length = 0; - for (let i = 0; i < this.bytesInLength; i++) { - length += this.input[this.location] * Math.pow(Math.pow(2, 8), i); + for (let i = 0; i < bytesInLength; i++) { + if (bigEndian) { + length = (length << 8) + this.input[this.location]; + } else { + length += this.input[this.location] * Math.pow(Math.pow(2, 8), i); + } this.location++; } diff --git a/tests/operations/tests/ParseTLV.mjs b/tests/operations/tests/ParseTLV.mjs index 5c99eee2..9033848d 100644 --- a/tests/operations/tests/ParseTLV.mjs +++ b/tests/operations/tests/ParseTLV.mjs @@ -52,5 +52,46 @@ TestRegister.addTests([ "args": [1, 4, true] // length value is patently wrong, should be ignored by BER. } ] + }, + { + name: "Parse TLV: BER long-form length (two-byte length encoding)", + input: "\x01\x82\x01\x00" + "A".repeat(256) + "\x02\x03\x41\x42\x43", + expectedOutput: JSON.stringify([ + {"key": [1], "length": 256, "value": Array(256).fill(65)}, + {"key": [2], "length": 3, "value": [65, 66, 67]} + ], null, 4), + recipeConfig: [ + { + "op": "Parse TLV", + "args": [1, 1, true] + } + ] + }, + { + name: "Parse TLV: BER long-form length (one-byte length encoding)", + input: "\x01\x81\x80" + "B".repeat(128), + expectedOutput: JSON.stringify([ + {"key": [1], "length": 128, "value": Array(128).fill(66)} + ], null, 4), + recipeConfig: [ + { + "op": "Parse TLV", + "args": [1, 1, true] + } + ] + }, + { + name: "Parse TLV: BER multiple entries with mixed short and long-form lengths", + input: "\x01\x05\x48\x65\x6c\x6c\x6f\x02\x81\x05\x57\x6f\x72\x6c\x64", + expectedOutput: JSON.stringify([ + {"key": [1], "length": 5, "value": [72, 101, 108, 108, 111]}, + {"key": [2], "length": 5, "value": [87, 111, 114, 108, 100]} + ], null, 4), + recipeConfig: [ + { + "op": "Parse TLV", + "args": [1, 1, true] + } + ] } ]); From 8105e3eb070aedac8b10aaa895ecbeb14279b147 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sat, 20 Jun 2026 10:03:12 +0200 Subject: [PATCH 06/19] fix: Gzip comment with header checksum produces corrupt streams (#2288) --- src/core/operations/Gzip.mjs | 4 +-- tests/operations/tests/Gzip.mjs | 60 +++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/core/operations/Gzip.mjs b/src/core/operations/Gzip.mjs index 093ae6a4..43eaf091 100644 --- a/src/core/operations/Gzip.mjs +++ b/src/core/operations/Gzip.mjs @@ -74,13 +74,11 @@ class Gzip extends Operation { } if (comment.length) { options.flags.comment = true; + options.flags.fcomment = true; options.comment = comment; } const gzipObj = new Zlib.Gzip(new Uint8Array(input), options); const compressed = new Uint8Array(gzipObj.compress()); - if (options.flags.comment && !(compressed[3] & 0x10)) { - compressed[3] |= 0x10; - } return compressed.buffer; } diff --git a/tests/operations/tests/Gzip.mjs b/tests/operations/tests/Gzip.mjs index c9b2b8ca..a936f5d0 100644 --- a/tests/operations/tests/Gzip.mjs +++ b/tests/operations/tests/Gzip.mjs @@ -86,4 +86,64 @@ TestRegister.addTests([ } ] }, + { + name: "Gzip: Comment with checksum round-trips through Gunzip", + input: "hello hello hello", + expectedOutput: "hello hello hello", + recipeConfig: [ + { + op: "Gzip", + args: ["Dynamic Huffman Coding", "", "test", true] + }, + { + op: "Gunzip", + args: [] + } + ] + }, + { + name: "Gzip: Filename and comment with checksum round-trips through Gunzip", + input: "The quick brown fox jumped over the slow dog", + expectedOutput: "The quick brown fox jumped over the slow dog", + recipeConfig: [ + { + op: "Gzip", + args: ["Dynamic Huffman Coding", "file.txt", "a comment", true] + }, + { + op: "Gunzip", + args: [] + } + ] + }, + { + name: "Gzip: No comment, with checksum round-trips through Gunzip", + input: "The quick brown fox jumped over the slow dog", + expectedOutput: "The quick brown fox jumped over the slow dog", + recipeConfig: [ + { + op: "Gzip", + args: ["Dynamic Huffman Coding", "", "", true] + }, + { + op: "Gunzip", + args: [] + } + ] + }, + { + name: "Gzip: No options round-trips through Gunzip", + input: "The quick brown fox jumped over the slow dog", + expectedOutput: "The quick brown fox jumped over the slow dog", + recipeConfig: [ + { + op: "Gzip", + args: ["Dynamic Huffman Coding", "", "", false] + }, + { + op: "Gunzip", + args: [] + } + ] + }, ]); From 64fc664479bb03f3f026832141d4af2e34ef9091 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sat, 20 Jun 2026 11:41:53 +0200 Subject: [PATCH 07/19] fix: MIME Decoding corrupts non-ASCII characters in Base64-encoded words (#2291) --- src/core/operations/MIMEDecoding.mjs | 2 +- tests/operations/tests/MIMEDecoding.mjs | 33 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/core/operations/MIMEDecoding.mjs b/src/core/operations/MIMEDecoding.mjs index 7b52fbdd..4ba04c18 100644 --- a/src/core/operations/MIMEDecoding.mjs +++ b/src/core/operations/MIMEDecoding.mjs @@ -87,7 +87,7 @@ class MIMEDecoding extends Operation { end = cur + j + "?=".length; if (encoding.toLowerCase() === "b") { - text = fromBase64(text); + text = fromBase64(text, undefined, "byteArray"); } else if (encoding.toLowerCase() === "q") { text = this.parseQEncodedWord(text); } else { diff --git a/tests/operations/tests/MIMEDecoding.mjs b/tests/operations/tests/MIMEDecoding.mjs index b99fc489..2c362542 100644 --- a/tests/operations/tests/MIMEDecoding.mjs +++ b/tests/operations/tests/MIMEDecoding.mjs @@ -75,6 +75,39 @@ TestRegister.addTests([ } ] }, + { + name: "UTF-8 Base64 non-ASCII", + input: "Subject: =?UTF-8?B?Y2Fmw6k=?=", + expectedOutput: "Subject: café", + recipeConfig: [ + { + "op": "MIME Decoding", + "args": [] + } + ] + }, + { + name: "UTF-8 Base64 multibyte CJK", + input: "Subject: =?UTF-8?B?5pel5pys6Kqe?=", + expectedOutput: "Subject: 日本語", + recipeConfig: [ + { + "op": "MIME Decoding", + "args": [] + } + ] + }, + { + name: "UTF-8 Base64 ASCII-only", + input: "Subject: =?UTF-8?B?aGVsbG8=?=", + expectedOutput: "Subject: hello", + recipeConfig: [ + { + "op": "MIME Decoding", + "args": [] + } + ] + }, { name: "ISO Decoding", input: "From: =?US-ASCII?Q?Keith_Moore?= \nTo: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= \nCC: =?ISO-8859-1?Q?Andr=E9?= Pirard \nSubject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=\n=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=", From 08e5c13da4b2404e824a8e358f1093393ee41780 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sat, 20 Jun 2026 11:49:47 +0200 Subject: [PATCH 08/19] fix Dechunk HTTP Response leaks terminating chunk and trailers into output (#2290) --- src/core/operations/DechunkHTTPResponse.mjs | 5 +- .../operations/tests/DechunkHTTPResponse.mjs | 66 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/operations/tests/DechunkHTTPResponse.mjs diff --git a/src/core/operations/DechunkHTTPResponse.mjs b/src/core/operations/DechunkHTTPResponse.mjs index da2eb437..40b97c7a 100644 --- a/src/core/operations/DechunkHTTPResponse.mjs +++ b/src/core/operations/DechunkHTTPResponse.mjs @@ -45,12 +45,15 @@ class DechunkHTTPResponse extends Operation { const lineEndingsLength = lineEndings.length; let chunkSize = parseInt(input.slice(0, chunkSizeEnd), 16); while (!isNaN(chunkSize)) { + if (chunkSize === 0) { + break; + } chunks.push(input.slice(chunkSizeEnd, chunkSize + chunkSizeEnd)); input = input.slice(chunkSizeEnd + chunkSize + lineEndingsLength); chunkSizeEnd = input.indexOf(lineEndings) + lineEndingsLength; chunkSize = parseInt(input.slice(0, chunkSizeEnd), 16); } - return chunks.join("") + input; + return chunks.join(""); } } diff --git a/tests/operations/tests/DechunkHTTPResponse.mjs b/tests/operations/tests/DechunkHTTPResponse.mjs new file mode 100644 index 00000000..2a678c89 --- /dev/null +++ b/tests/operations/tests/DechunkHTTPResponse.mjs @@ -0,0 +1,66 @@ +/** + * DechunkHTTPResponse operation tests. + * + * @author Willi Ballenthin + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Dechunk HTTP response: CRLF line endings", + input: "7\r\nMozilla\r\n9\r\nDeveloper\r\n7\r\nNetwork\r\n0\r\n\r\n", + expectedOutput: "MozillaDeveloperNetwork", + recipeConfig: [ + { + op: "Dechunk HTTP response", + args: [], + }, + ], + }, + { + name: "Dechunk HTTP response: LF line endings", + input: "7\nMozilla\n9\nDeveloper\n7\nNetwork\n0\n\n", + expectedOutput: "MozillaDeveloperNetwork", + recipeConfig: [ + { + op: "Dechunk HTTP response", + args: [], + }, + ], + }, + { + name: "Dechunk HTTP response: single chunk", + input: "5\r\nHello\r\n0\r\n\r\n", + expectedOutput: "Hello", + recipeConfig: [ + { + op: "Dechunk HTTP response", + args: [], + }, + ], + }, + { + name: "Dechunk HTTP response: trailing headers discarded", + input: "7\nMozilla\n9\nDeveloper\n7\nNetwork\n0\nExpires: Wed, 21 Oct 2015 07:28:00 GMT\n", + expectedOutput: "MozillaDeveloperNetwork", + recipeConfig: [ + { + op: "Dechunk HTTP response", + args: [], + }, + ], + }, + { + name: "Dechunk HTTP response: hex chunk sizes", + input: "a\r\n0123456789\r\n0\r\n\r\n", + expectedOutput: "0123456789", + recipeConfig: [ + { + op: "Dechunk HTTP response", + args: [], + }, + ], + }, +]); From 0d2af8ce003ce444c9fb00a07aa3eb972653baa2 Mon Sep 17 00:00:00 2001 From: min23asdw <76154445+min23asdw@users.noreply.github.com> Date: Sat, 20 Jun 2026 17:40:37 +0700 Subject: [PATCH 09/19] fix: jsonata $base64decode/$base64encode in Web Worker (#2275) --- src/core/operations/Jsonata.mjs | 12 ++++++++++++ tests/browser/02_ops.js | 1 + tests/operations/tests/Jsonata.mjs | 23 +++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/core/operations/Jsonata.mjs b/src/core/operations/Jsonata.mjs index 82cc4d39..04259343 100644 --- a/src/core/operations/Jsonata.mjs +++ b/src/core/operations/Jsonata.mjs @@ -51,6 +51,18 @@ class JsonataQuery extends Operation { try { const expression = jsonata(query); + // Override built-in base64 functions which fail in Web Worker + // context where `window` is undefined. The jsonata library falls + // back to `global.Buffer` which also does not exist in workers. + // `atob`/`btoa` are available in both browser and worker scopes. + expression.registerFunction("base64decode", (str) => { + if (typeof str === "undefined") return undefined; + return atob(str); + }, ""); + expression.registerFunction("base64encode", (str) => { + if (typeof str === "undefined") return undefined; + return btoa(str); + }, ""); result = await expression.evaluate(jsonObj); } catch (err) { throw new OperationError( diff --git a/tests/browser/02_ops.js b/tests/browser/02_ops.js index 9139a53a..bb1a5e78 100644 --- a/tests/browser/02_ops.js +++ b/tests/browser/02_ops.js @@ -218,6 +218,7 @@ module.exports = { testOpHtml(browser, "JSON Beautify", "{a:1}", ".json-dict .json-literal", "1"); // testOp(browser, "JSON Minify", "test input", "test_output"); // testOp(browser, "JSON to CSV", "test input", "test_output"); + testOp(browser, "Jsonata Query", '{"a": "SGVsbG8gV29ybGQh"}', '"Hello World!"', ["$base64decode($.a)"]); // testOp(browser, "JWT Decode", "test input", "test_output"); // testOp(browser, "JWT Sign", "test input", "test_output"); // testOp(browser, "JWT Verify", "test input", "test_output"); diff --git a/tests/operations/tests/Jsonata.mjs b/tests/operations/tests/Jsonata.mjs index fb46a961..54ecf34c 100644 --- a/tests/operations/tests/Jsonata.mjs +++ b/tests/operations/tests/Jsonata.mjs @@ -548,4 +548,27 @@ TestRegister.addTests([ }, ], }, + // Base64 functions (issue #2063) + { + name: "Jsonata: $base64decode", + input: "{}", + expectedOutput: '"Hello World!"', + recipeConfig: [ + { + op: "Jsonata Query", + args: ['$base64decode("SGVsbG8gV29ybGQh")'], + }, + ], + }, + { + name: "Jsonata: $base64encode", + input: "{}", + expectedOutput: '"SGVsbG8gV29ybGQh"', + recipeConfig: [ + { + op: "Jsonata Query", + args: ['$base64encode("Hello World!")'], + }, + ], + }, ]); From a0a369a7efa9ace61b8114afcd5184f653a05e48 Mon Sep 17 00:00:00 2001 From: Leon Zandman Date: Sat, 20 Jun 2026 13:01:14 +0200 Subject: [PATCH 10/19] Fix uncaught TypeError in "Show on map" operation. (#2453) --- src/core/operations/ShowOnMap.mjs | 10 +++++++ tests/operations/tests/ShowOnMap.mjs | 39 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 tests/operations/tests/ShowOnMap.mjs diff --git a/src/core/operations/ShowOnMap.mjs b/src/core/operations/ShowOnMap.mjs index d75c2aa6..2eab5140 100644 --- a/src/core/operations/ShowOnMap.mjs +++ b/src/core/operations/ShowOnMap.mjs @@ -71,6 +71,16 @@ class ShowOnMap extends Operation { } latLong = latLong.replace(/[,]$/, ""); latLong = latLong.replace(/°/g, ""); + + // The map requires a latitude and longitude pair. If the conversion only produced a + // single value (e.g. because the chosen input delimiter didn't match the input), bail + // out with a helpful message rather than passing it on to the map, which would throw an + // uncaught TypeError in the browser. + const coords = latLong.split(",").map(v => v.trim()); + if (coords.length !== 2 || coords.some(v => v === "" || isNaN(Number(v)))) { + throw new OperationError(`Could not show coordinates '${latLong}' on the map. Expected a latitude and longitude pair - check that the input format and delimiter are correct.`); + } + return latLong; } return input; diff --git a/tests/operations/tests/ShowOnMap.mjs b/tests/operations/tests/ShowOnMap.mjs new file mode 100644 index 00000000..8605ae70 --- /dev/null +++ b/tests/operations/tests/ShowOnMap.mjs @@ -0,0 +1,39 @@ +/** + * Show on map tests + * + * @author Leon Zandman [leon@wirwar.com] + * + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Show on map: valid coordinate pair", + input: "51.5007, -0.1246", + // The presented output is the Leaflet map HTML; just check the coordinates made it through. + expectedMatch: /51\.5007,-0\.1246/, + recipeConfig: [ + { + op: "Show on map", + args: [13, "Auto", "Auto"] + }, + ], + }, + { + // Regression test: a comma-separated input with the delimiter set to "\n" used to be + // mis-detected as a single Degrees Decimal Minutes value (1° 24' = 1.4°), producing a single + // coordinate. That single value was then passed to Leaflet's setView([1.4], ...), throwing + // an uncaught "Cannot read properties of null (reading 'lat')" TypeError in the browser. + name: "Show on map: single value is rejected with a helpful error", + input: "1, 24", + expectedOutput: "Could not show coordinates '1.4' on the map. Expected a latitude and longitude pair - check that the input format and delimiter are correct.", + recipeConfig: [ + { + op: "Show on map", + args: [13, "Auto", "\\n"] + }, + ], + }, +]); From 080357a4f5738931b220a702537c1e4fe0d33fba Mon Sep 17 00:00:00 2001 From: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> Date: Mon, 22 Jun 2026 11:51:12 +0100 Subject: [PATCH 11/19] Improve parameter validation for a number of operations where exceptions otherwise caused. (#2586) --- src/core/operations/BLAKE3.mjs | 6 ++- src/core/operations/BitShiftLeft.mjs | 5 ++- .../PseudoRandomNumberGenerator.mjs | 3 +- src/core/operations/ToBase.mjs | 8 ++-- src/core/operations/ToBinary.mjs | 5 ++- src/core/operations/XORBruteForce.mjs | 5 ++- src/core/operations/XORChecksum.mjs | 4 +- tests/operations/tests/BLAKE3.mjs | 40 ++++++++++++++++++- 8 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/core/operations/BLAKE3.mjs b/src/core/operations/BLAKE3.mjs index 53f7fdd6..a22eb0b8 100644 --- a/src/core/operations/BLAKE3.mjs +++ b/src/core/operations/BLAKE3.mjs @@ -30,7 +30,11 @@ class BLAKE3 extends Operation { this.args = [ { "name": "Size (bytes)", - "type": "number" + "type": "number", + "value": 16, + "min": 1, + "max": 65535, // arbitrary limit to prevent resource exhaustion + "integer": true, }, { "name": "Key", "type": "string", diff --git a/src/core/operations/BitShiftLeft.mjs b/src/core/operations/BitShiftLeft.mjs index cd9f4568..540ab659 100644 --- a/src/core/operations/BitShiftLeft.mjs +++ b/src/core/operations/BitShiftLeft.mjs @@ -27,7 +27,10 @@ class BitShiftLeft extends Operation { { "name": "Amount", "type": "number", - "value": 1 + "value": 1, + "min": 0, + "max": 7, + "integer": true, } ]; } diff --git a/src/core/operations/PseudoRandomNumberGenerator.mjs b/src/core/operations/PseudoRandomNumberGenerator.mjs index 53150566..da23c4de 100644 --- a/src/core/operations/PseudoRandomNumberGenerator.mjs +++ b/src/core/operations/PseudoRandomNumberGenerator.mjs @@ -31,7 +31,8 @@ class PseudoRandomNumberGenerator extends Operation { { "name": "Number of bytes", "type": "number", - "value": 32 + "value": 32, + "min": 1 }, { "name": "Output as", diff --git a/src/core/operations/ToBase.mjs b/src/core/operations/ToBase.mjs index 09a91571..4bf7ae83 100644 --- a/src/core/operations/ToBase.mjs +++ b/src/core/operations/ToBase.mjs @@ -28,7 +28,10 @@ class ToBase extends Operation { { "name": "Radix", "type": "number", - "value": 36 + "value": 36, + "min": 2, + "max": 36, + "integer": true, } ]; } @@ -43,9 +46,6 @@ class ToBase extends Operation { throw new OperationError("Error: Input must be a number"); } const radix = args[0]; - if (radix < 2 || radix > 36) { - throw new OperationError("Error: Radix argument must be between 2 and 36"); - } return input.toString(radix); } diff --git a/src/core/operations/ToBinary.mjs b/src/core/operations/ToBinary.mjs index ba72a55b..b19f94f0 100644 --- a/src/core/operations/ToBinary.mjs +++ b/src/core/operations/ToBinary.mjs @@ -35,7 +35,10 @@ class ToBinary extends Operation { { "name": "Byte Length", "type": "number", - "value": 8 + "value": 8, + "min": 1, + "max": 256, // arbitrary - significantly larger than word size for any known machine ("640k ought to be enough for anybody") + "integer": true } ]; } diff --git a/src/core/operations/XORBruteForce.mjs b/src/core/operations/XORBruteForce.mjs index 8c097731..96ea8ad0 100644 --- a/src/core/operations/XORBruteForce.mjs +++ b/src/core/operations/XORBruteForce.mjs @@ -31,7 +31,10 @@ class XORBruteForce extends Operation { { "name": "Key length", "type": "number", - "value": 1 + "value": 1, + "min": 1, + "max": 2, + "integer": true }, { "name": "Sample length", diff --git a/src/core/operations/XORChecksum.mjs b/src/core/operations/XORChecksum.mjs index ca9c6fac..338b4bea 100644 --- a/src/core/operations/XORChecksum.mjs +++ b/src/core/operations/XORChecksum.mjs @@ -7,7 +7,7 @@ import Operation from "../Operation.mjs"; import Utils from "../Utils.mjs"; import { toHex } from "../lib/Hex.mjs"; -import OperationError from "../errors/OperationError.mjs"; +import OperationError from "../errors/OperationError.mjs"; /** * XOR Checksum operation @@ -43,7 +43,7 @@ class XORChecksum extends Operation { run(input, args) { const blocksize = args[0]; - + if (!Number.isInteger(blocksize) || blocksize <= 0) { throw new OperationError("Blocksize must be a positive integer."); } diff --git a/tests/operations/tests/BLAKE3.mjs b/tests/operations/tests/BLAKE3.mjs index b3c14e99..e15144b2 100644 --- a/tests/operations/tests/BLAKE3.mjs +++ b/tests/operations/tests/BLAKE3.mjs @@ -69,5 +69,43 @@ TestRegister.addTests([ { "op": "BLAKE3", "args": [16390, "ThiskeyisexactlythirtytwoBytesLo"] } ] - } + }, +// test vectors from https://github.com/BLAKE3-team/BLAKE3/blob/master/test_vectors/test_vectors.json + { + name: "BLAKE3: Std test vector - 0 bytes input, plain hash", + input: "", + expectedOutput: "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262e00f03e7b69af26b7faaf09fcd333050338ddfe085b8cc869ca98b206c08243a26f5487789e8f660afe6c99ef9e0c52b92e7393024a80459cf91f476f9ffdbda7001c22e159b402631f277ca96f2defdf1078282314e763699a31c5363165421cce14d", + recipeConfig: [ + { + "op": "BLAKE3", + "args": [131, ""] + } + ] + }, + { + name: "BLAKE3: Std test vector - 0 bytes input, keyed hash", + input: "", + expectedOutput: "92b2b75604ed3c761f9d6f62392c8a9227ad0ea3f09573e783f1498a4ed60d26b18171a2f22a4b94822c701f107153dba24918c4bae4d2945c20ece13387627d3b73cbf97b797d5e59948c7ef788f54372df45e45e4293c7dc18c1d41144a9758be58960856be1eabbe22c2653190de560ca3b2ac4aa692a9210694254c371e851bc8f", + recipeConfig: [ + { + "op": "BLAKE3", + "args": [131, "whats the Elvish word for friend"] + } + ] + }, + { + name: "BLAKE3: Std test vector - 7 bytes input, keyed hash", + input: "0001020304050607", + expectedOutput: "be2f5495c61cba1bb348a34948c004045e3bd4dae8f0fe82bf44d0da245a060048eb5e68ce6dea1eb0229e144f578b3aa7e9f4f85febd135df8525e6fe40c6f0340d13dd09b255ccd5112a94238f2be3c0b5b7ecde06580426a93e0708555a265305abf86d874e34b4995b788e37a823491f25127a502fe0704baa6bfdf04e76c13276", + recipeConfig: [ + { + "op": "From Hex", + args: [], + }, + { + "op": "BLAKE3", + "args": [131, "whats the Elvish word for friend"] + } + ] + }, ]); From 9f87fec52d2780d23be73385205587a55e307596 Mon Sep 17 00:00:00 2001 From: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> Date: Mon, 22 Jun 2026 11:52:26 +0100 Subject: [PATCH 12/19] =?UTF-8?q?Clean=20up/rationalise=20webpack=20paths?= =?UTF-8?q?=20and=20thereby=20increase=20compatibility=20for=20Win?= =?UTF-8?q?=E2=80=A6=20(#2585)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webpack.config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webpack.config.js b/webpack.config.js index 4c6c00ba..555a33c3 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -88,8 +88,8 @@ module.exports = { from: "tesseract/**/*", to: "assets/" }, { - context: "node_modules/tesseract.js/", - from: "dist/worker.min.js", + context: "node_modules/tesseract.js/dist", + from: "worker.min.js", to: "assets/tesseract" }, { context: "node_modules/tesseract.js-core/", @@ -221,7 +221,7 @@ module.exports = { }, { // Third party images are inlined test: /\.(png|jpg|gif)$/, - exclude: /web\/static/, + include: /node_modules/, type: "asset/inline", }, ] From 0e50d32ec5155cbf2b72d10b9b0357b9ddbca956 Mon Sep 17 00:00:00 2001 From: Zain Nadeem Date: Wed, 24 Jun 2026 21:39:01 +0500 Subject: [PATCH 13/19] Fix stale presenter after expected operation errors (#2589) Co-authored-by: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> (tweaked tests) --- src/core/Recipe.mjs | 2 ++ tests/operations/tests/RenderPDF.mjs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/core/Recipe.mjs b/src/core/Recipe.mjs index 0886e994..0a2e217d 100755 --- a/src/core/Recipe.mjs +++ b/src/core/Recipe.mjs @@ -241,9 +241,11 @@ class Recipe { // Cannot rely on `err instanceof OperationError` here as extending // native types is not fully supported yet. dish.set(err.message, "string"); + this.lastRunOp = null; return i; } else if (err instanceof DishError || err?.type === "DishError") { dish.set(err.message, "string"); + this.lastRunOp = null; return i; } else { const e = typeof err == "string" ? { message: err } : err; diff --git a/tests/operations/tests/RenderPDF.mjs b/tests/operations/tests/RenderPDF.mjs index f359aa20..ff9c3e5a 100644 --- a/tests/operations/tests/RenderPDF.mjs +++ b/tests/operations/tests/RenderPDF.mjs @@ -7,6 +7,9 @@ import TestRegister from "../../lib/TestRegister.mjs"; +const oversizedPdfLikeInput = "%PDF-1.0\n" + "A".repeat(5000); + + TestRegister.addTests([ { name: "RenderPDF", @@ -34,4 +37,19 @@ TestRegister.addTests([ } ], }, + { + name: "RenderPDF followed by Generate QR Code error returns plain text", + input: oversizedPdfLikeInput, + expectedOutput: "Error generating QR code. (Error: Too much data)", + recipeConfig: [ + { + "op": "Render PDF", + "args": ["Raw"] + }, + { + "op": "Generate QR Code", + "args": ["PNG", 1, 0, "High"] + } + ], + }, ]); From bd4c59cf34bfa4b1ae06839db70936786c5702df Mon Sep 17 00:00:00 2001 From: Kirill Date: Thu, 25 Jun 2026 14:59:33 +0300 Subject: [PATCH 14/19] Handle empty Generate Image mode (#2598) --- src/core/operations/GenerateImage.mjs | 4 ++++ tests/operations/tests/Image.mjs | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/core/operations/GenerateImage.mjs b/src/core/operations/GenerateImage.mjs index 053e4ba1..c276213d 100644 --- a/src/core/operations/GenerateImage.mjs +++ b/src/core/operations/GenerateImage.mjs @@ -74,6 +74,10 @@ class GenerateImage extends Operation { Bits: 1 / 8, }; + if (!Object.hasOwn(bytePerPixelMap, mode)) { + throw new OperationError(`Unsupported Mode: (${mode})`); + } + const bytesPerPixel = bytePerPixelMap[mode]; if (bytesPerPixel > 0 && input.length % bytesPerPixel !== 0) { diff --git a/tests/operations/tests/Image.mjs b/tests/operations/tests/Image.mjs index 1f450433..fe6cab10 100644 --- a/tests/operations/tests/Image.mjs +++ b/tests/operations/tests/Image.mjs @@ -45,6 +45,17 @@ TestRegister.addTests([ { op: "Render Image", args: ["Base64"] } ] }, + { + name: "Generate Image: empty mode", + input: "", + expectedOutput: "Unsupported Mode: ()", + recipeConfig: [ + { + op: "Generate Image", + args: ["", 8, 64] + } + ] + }, { name: "Extract EXIF: nothing", input: "", From 6717ae1bc32673d006fd37eb8e477b61463652a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 09:24:51 +0100 Subject: [PATCH 15/19] chore (deps): bump the minor-updates group with 2 updates (#2603) 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 46d2fa53..edea67ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "bootstrap-colorpicker": "^3.4.0", "bootstrap-material-design": "^4.1.3", "browserify-zlib": "^0.2.0", - "bson": "^7.2.0", + "bson": "^7.3.0", "buffer": "^6.0.3", "cbor": "10.0.12", "chi-squared": "^1.1.0", @@ -133,7 +133,7 @@ "css-loader": "^7.1.4", "eslint": "^9.39.4", "eslint-plugin-jsdoc": "^50.8.0", - "globals": "^17.6.0", + "globals": "^17.7.0", "grunt": "^1.6.2", "grunt-chmod": "~1.1.1", "grunt-concurrent": "^3.0.0", @@ -6293,9 +6293,9 @@ } }, "node_modules/bson": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz", - "integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-7.3.0.tgz", + "integrity": "sha512-WmjjMEwFwZHmGnAb7wn90MhkiT+mTm4x/rLj7dvAPWfwnVWDXhLun2e+UM88MJoDGW624yzZglVX/zTBy9ZZMw==", "license": "Apache-2.0", "engines": { "node": ">=20.19.0" @@ -10236,9 +10236,9 @@ } }, "node_modules/globals": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", - "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.7.0.tgz", + "integrity": "sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index f20fba60..2ac0d47d 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "css-loader": "^7.1.4", "eslint": "^9.39.4", "eslint-plugin-jsdoc": "^50.8.0", - "globals": "^17.6.0", + "globals": "^17.7.0", "grunt": "^1.6.2", "grunt-chmod": "~1.1.1", "grunt-concurrent": "^3.0.0", @@ -111,7 +111,7 @@ "bootstrap-colorpicker": "^3.4.0", "bootstrap-material-design": "^4.1.3", "browserify-zlib": "^0.2.0", - "bson": "^7.2.0", + "bson": "^7.3.0", "buffer": "^6.0.3", "cbor": "10.0.12", "chi-squared": "^1.1.0", From 9672a8f870f170efde39fdf5162f53f8c61fb34f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 09:25:12 +0100 Subject: [PATCH 16/19] chore (deps): bump actions/checkout from 6.0.3 to 7.0.0 in the actions-dependencies group (#2601) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/master.yml | 2 +- .github/workflows/pull_requests.yml | 2 +- .github/workflows/releases.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index c03810a8..e8a120ed 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -16,7 +16,7 @@ jobs: pages: write runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Set node version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 diff --git a/.github/workflows/pull_requests.yml b/.github/workflows/pull_requests.yml index fd5ff732..8424e16d 100644 --- a/.github/workflows/pull_requests.yml +++ b/.github/workflows/pull_requests.yml @@ -12,7 +12,7 @@ jobs: main: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Set node version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 13f45cb1..ae47bf4f 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -22,7 +22,7 @@ jobs: contents: write runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Set node version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 @@ -110,7 +110,7 @@ jobs: needs: main runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Set node version uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 From e112da3c12cebd1cf65911916e7df43b0fda8c52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 11:08:47 +0100 Subject: [PATCH 17/19] chore (deps): bump the patch-updates group with 8 updates (#2602) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 256 ++++++++++++++++++++++++++++++++-------------- package.json | 14 +-- 2 files changed, 185 insertions(+), 85 deletions(-) diff --git a/package-lock.json b/package-lock.json index edea67ed..048e433b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,7 +85,7 @@ "path": "^0.12.7", "popper.js": "^1.16.1", "process": "^0.11.10", - "protobufjs": "^8.6.4", + "protobufjs": "^8.6.5", "punycode.js": "^2.3.1", "qr-image": "^3.2.0", "reflect-metadata": "^0.2.2", @@ -94,7 +94,7 @@ "snackbarjs": "^1.1.0", "sortablejs": "^1.15.7", "split.js": "^1.6.5", - "sql-formatter": "^15.8.1", + "sql-formatter": "^15.8.2", "ssdeep.js": "0.0.3", "stream-browserify": "^3.0.0", "tesseract.js": "^7.0.0", @@ -102,7 +102,7 @@ "unorm": "^1.6.0", "url": "^0.11.4", "utf8": "^3.0.0", - "uuid": "^14.0.0", + "uuid": "^14.0.1", "vkbeautify": "^0.99.3", "xpath": "0.0.34", "xregexp": "^5.1.2", @@ -114,13 +114,13 @@ "@babel/plugin-transform-runtime": "^7.29.7", "@babel/preset-env": "^7.29.7", "@babel/runtime": "^7.29.7", - "@codemirror/commands": "^6.10.3", + "@codemirror/commands": "^6.10.4", "@codemirror/language": "^6.12.3", "@codemirror/search": "^6.7.1", "@codemirror/state": "^6.5.4", - "@codemirror/view": "^6.43.1", - "@puppeteer/browsers": "3.0.4", - "autoprefixer": "^10.5.0", + "@codemirror/view": "^6.43.2", + "@puppeteer/browsers": "3.0.5", + "autoprefixer": "^10.5.1", "babel-loader": "^10.1.1", "base64-loader": "^1.0.0", "chromedriver": "^148.0.4", @@ -1848,14 +1848,14 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", - "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.4.tgz", + "integrity": "sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg==", "dev": true, "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.6.0", + "@codemirror/state": "^6.7.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } @@ -1888,9 +1888,9 @@ } }, "node_modules/@codemirror/state": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", - "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.7.0.tgz", + "integrity": "sha512-Zbl9NyscLMZkfXPQnNAIIAFftidrA1UbcJEIMp24C0Bukc2I5T8wJS0wsXYsnDOqCFJUeJ1BITGNs5CqPDSmSg==", "dev": true, "license": "MIT", "dependencies": { @@ -1898,13 +1898,13 @@ } }, "node_modules/@codemirror/view": { - "version": "6.43.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.1.tgz", - "integrity": "sha512-+BIjw/AG3tDQ4pJgTLPYdAW25eDE66YsvM4LKyVPgGzVgZ4a9Wj1SRX8kPVKgBDdPt8oHtZ15F0qx7p0oOHdHw==", + "version": "6.43.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.2.tgz", + "integrity": "sha512-8kU6WNRYBKV9Sw3cxNz+uSvUvx3tt+1qgupGFPubnbLFDHOgh5qQdIGmXcD7bkA/PROK6LDKVhKMpcY7H++Amg==", "dev": true, "license": "MIT", "dependencies": { - "@codemirror/state": "^6.6.0", + "@codemirror/state": "^6.7.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" @@ -4417,14 +4417,14 @@ "license": "MIT" }, "node_modules/@puppeteer/browsers": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.4.tgz", - "integrity": "sha512-HGM8iAmGTf+Y7t0373szVbTmt3d7vPkYL/1bpOkOFO0YUYLgSeuYBCzESklogNPvOBnZ/MRD5f07OkpqH1trtA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.5.tgz", + "integrity": "sha512-xYXNuEQmHNIPWWcbL/skf2KF7seyp7c1xmKFRk3wmdFx7VwBsKVrtOLKs8ecaezsKPsWeF1YsgwIiElAscaryA==", "dev": true, "license": "Apache-2.0", "dependencies": { "modern-tar": "^0.7.6", - "yargs": "^17.7.2" + "yargs": "^18.0.0" }, "bin": { "browsers": "lib/main-cli.js" @@ -4441,48 +4441,132 @@ } } }, + "node_modules/@puppeteer/browsers/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/@puppeteer/browsers/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dev": true, "license": "ISC", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=12" + "node": ">=20" } }, - "node_modules/@puppeteer/browsers/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "node_modules/@puppeteer/browsers/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@puppeteer/browsers/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@puppeteer/browsers/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/@puppeteer/browsers/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "dev": true, "license": "ISC", "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/@testim/chrome-version": { @@ -5531,9 +5615,9 @@ "license": "MIT" }, "node_modules/autoprefixer": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", - "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "version": "10.5.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.1.tgz", + "integrity": "sha512-jwM2pcTuCWUoN70FEvf5XrXyDbUgRURK4FnU8v0jWZZYU/KkVvN9T33mu1sVLFY9JW3kTWzKheEpn6xYLRc/VA==", "dev": true, "funding": [ { @@ -5551,8 +5635,8 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.28.2", - "caniuse-lite": "^1.0.30001787", + "browserslist": "^4.28.4", + "caniuse-lite": "^1.0.30001799", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -5725,9 +5809,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz", - "integrity": "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==", + "version": "2.10.40", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.40.tgz", + "integrity": "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -6259,9 +6343,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", "dev": true, "funding": [ { @@ -6279,10 +6363,10 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", "update-browserslist-db": "^1.2.3" }, "bin": { @@ -6474,9 +6558,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001788", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz", - "integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==", + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", "dev": true, "funding": [ { @@ -8692,9 +8776,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.339", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.339.tgz", - "integrity": "sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg==", + "version": "1.5.379", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.379.tgz", + "integrity": "sha512-v/qV5aV5EUA2pGilzUCq5/eyOloZAqDZBu9UMBIzgPpLlprjSR6zswsWBTv0KpqxLGUAZEwhO95ZCt7srymNVA==", "dev": true, "license": "ISC" }, @@ -10027,6 +10111,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -13814,11 +13911,14 @@ "license": "CC0-1.0" }, "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "version": "2.0.50", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", + "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/nodom": { "version": "2.4.0", @@ -15086,9 +15186,9 @@ "license": "MIT" }, "node_modules/protobufjs": { - "version": "8.6.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.6.4.tgz", - "integrity": "sha512-/+XMv9JalknuncEJSwsyEVlwcxVLKx2iaoSUXFZA86MJkdqyOdfrlB1sB7S6aKyUk9tl20YY+SgQe5J2sJHTcg==", + "version": "8.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.6.5.tgz", + "integrity": "sha512-zeE5LPpencAGXvsxyOYmEgJhxzHY8IsmPAFzstZVhDSVT8QH03q6gMZwZRaQGApevZbAL6u28ugs4CC+YKB2jQ==", "license": "BSD-3-Clause", "dependencies": { "long": "^5.3.2" @@ -16774,9 +16874,9 @@ "license": "BSD-3-Clause" }, "node_modules/sql-formatter": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.8.1.tgz", - "integrity": "sha512-nT2r90kTEYBuse9fe4r1Rp78v1mOBD35KsGc07Vo9eQSVa1TcTSnCS0zouf6BCmdzvmqBsBW+cYuBoYkHO/OWg==", + "version": "15.8.2", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.8.2.tgz", + "integrity": "sha512-kTYRg5FIcvsDtYUG2Qn9pYT6xKwiLJN5TTIvc5Mur6hIg4pSfdpHu8Yyu5bqESLHnVM3mXzD446cb2+uEaKZXg==", "license": "MIT", "dependencies": { "argparse": "^2.0.1", @@ -17858,9 +17958,9 @@ } }, "node_modules/uuid": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", - "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", + "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" diff --git a/package.json b/package.json index 2ac0d47d..ed678f33 100644 --- a/package.json +++ b/package.json @@ -44,13 +44,13 @@ "@babel/plugin-transform-runtime": "^7.29.7", "@babel/preset-env": "^7.29.7", "@babel/runtime": "^7.29.7", - "@codemirror/commands": "^6.10.3", + "@codemirror/commands": "^6.10.4", "@codemirror/language": "^6.12.3", "@codemirror/search": "^6.7.1", "@codemirror/state": "^6.5.4", - "@codemirror/view": "^6.43.1", - "@puppeteer/browsers": "3.0.4", - "autoprefixer": "^10.5.0", + "@codemirror/view": "^6.43.2", + "@puppeteer/browsers": "3.0.5", + "autoprefixer": "^10.5.1", "babel-loader": "^10.1.1", "base64-loader": "^1.0.0", "chromedriver": "^148.0.4", @@ -169,7 +169,7 @@ "path": "^0.12.7", "popper.js": "^1.16.1", "process": "^0.11.10", - "protobufjs": "^8.6.4", + "protobufjs": "^8.6.5", "punycode.js": "^2.3.1", "qr-image": "^3.2.0", "reflect-metadata": "^0.2.2", @@ -178,7 +178,7 @@ "snackbarjs": "^1.1.0", "sortablejs": "^1.15.7", "split.js": "^1.6.5", - "sql-formatter": "^15.8.1", + "sql-formatter": "^15.8.2", "ssdeep.js": "0.0.3", "stream-browserify": "^3.0.0", "tesseract.js": "^7.0.0", @@ -186,7 +186,7 @@ "unorm": "^1.6.0", "url": "^0.11.4", "utf8": "^3.0.0", - "uuid": "^14.0.0", + "uuid": "^14.0.1", "vkbeautify": "^0.99.3", "xpath": "0.0.34", "xregexp": "^5.1.2", From 2329a0a0e5f1d74f467e23115fae3abbdb918dcc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jun 2026 11:20:20 +0100 Subject: [PATCH 18/19] chore (deps): bump the docker-dependencies group with 2 updates (#2600) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index f70ba966..24eab9fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # Modifier --platform=$BUILDPLATFORM limits the platform to "BUILDPLATFORM" during buildx multi-platform builds # This is because npm "chromedriver" package is not compatiable with all platforms # For more info see: https://docs.docker.com/build/building/multi-platform/#cross-compilation -FROM --platform=$BUILDPLATFORM node:24-alpine@sha256:156b55f92e98ccd5ef49578a8cea0df4679826564bad1c9d4ef04462b9f0ded6 AS builder +FROM --platform=$BUILDPLATFORM node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd AS builder WORKDIR /app @@ -27,7 +27,7 @@ RUN npm run build ######################################### # Package static build files into nginx # ######################################### -FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:fafa1102c789119971b3d83f9293f1ef5526bc73583a12e13ff5cd1299ed8b6c AS cyberchef +FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:458ecbec226a23120713b35945bcdf0d6e4ea5bbec60c149ce1deca5d264071b AS cyberchef LABEL maintainer="GCHQ " From 275b594f7c8b0e39880f55e7c1f67dc0a4e73f92 Mon Sep 17 00:00:00 2001 From: GCHQDeveloper581 <63102987+GCHQDeveloper581@users.noreply.github.com> Date: Fri, 26 Jun 2026 13:07:33 +0100 Subject: [PATCH 19/19] Fix BigNumber deserialisation in Dish, and add tests (#2607) With ideas from: cyphercodes With ideas from: Sivachandran Paramasivam --- src/core/Dish.mjs | 6 +---- tests/browser/02_ops.js | 4 ++-- tests/node/tests/Dish.mjs | 19 +++++++++++++++ tests/operations/tests/Arithmetic.mjs | 33 +++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 tests/operations/tests/Arithmetic.mjs diff --git a/src/core/Dish.mjs b/src/core/Dish.mjs index 11b1ff9f..964380fb 100755 --- a/src/core/Dish.mjs +++ b/src/core/Dish.mjs @@ -292,11 +292,7 @@ class Dish { and reinitialise it as a BigNumber object. */ if (Object.keys(this.value).sort().equals(["c", "e", "s"])) { - const temp = new BigNumber(); - temp.c = this.value.c; - temp.e = this.value.e; - temp.s = this.value.s; - this.value = temp; + this.value = new BigNumber({ s: this.value.s, e: this.value.e, c: this.value.c, _isBigNumber: true}); return true; } return false; diff --git a/tests/browser/02_ops.js b/tests/browser/02_ops.js index bb1a5e78..caea3532 100644 --- a/tests/browser/02_ops.js +++ b/tests/browser/02_ops.js @@ -346,8 +346,8 @@ module.exports = { // testOp(browser, "Strip HTTP headers", "test input", "test_output"); // testOp(browser, "Subsection", "test input", "test_output"); // testOp(browser, "Substitute", "test input", "test_output"); - // testOp(browser, "Subtract", "test input", "test_output"); - // testOp(browser, "Sum", "test input", "test_output"); + testOp(browser, "Subtract", "321,123,test", "198", ["Comma"]); + testOp(browser, "Sum", "321,123,test", "444", ["Comma"]); // testOp(browser, "Swap endianness", "test input", "test_output"); // testOp(browser, "Symmetric Difference", "test input", "test_output"); testOpHtml(browser, "Syntax highlighter", "var a = [4,5,6]", ".hljs-selector-attr", "[4,5,6]"); diff --git a/tests/node/tests/Dish.mjs b/tests/node/tests/Dish.mjs index 58da00bf..a1b1dd7d 100644 --- a/tests/node/tests/Dish.mjs +++ b/tests/node/tests/Dish.mjs @@ -9,4 +9,23 @@ TestRegister.addApiTests([ assert(dish.presentAs); }), + it("Disk - should not error on serialized BigNumber (0)", () => { + const dish = new Dish({ s: 1, e: 0, c: [0] }, Dish.BIG_NUMBER); + assert.strictEqual(dish.value.toString(), "0"); + }), + + it("Dish - should not error on serialized BigNumber (1)", () => { + const dish = new Dish({ c: [1], e: 0, s: 1 }, Dish.BIG_NUMBER); + assert.strictEqual(dish.value.toString(), "1"); + }), + + it("Dish - should not error on serialized BigNumber (-100)", () => { + const dish = new Dish({ s: -1, e: 2, c: [100] }, Dish.BIG_NUMBER); + assert.strictEqual(dish.value.toString(), "-100"); + }), + + it("Dish - should not error on serialized BigNumber (NaN)", () => { + const dish = new Dish({ s: null, e: null, c: null }, Dish.BIG_NUMBER); + assert.strictEqual(dish.value.toString(), "NaN"); + }), ]); diff --git a/tests/operations/tests/Arithmetic.mjs b/tests/operations/tests/Arithmetic.mjs new file mode 100644 index 00000000..be62baed --- /dev/null +++ b/tests/operations/tests/Arithmetic.mjs @@ -0,0 +1,33 @@ +/** + * Tests for arithmetical operations + * + * @copyright Crown Copyright 2026 + * @license Apache-2.0 + */ + +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Subtract", + input: "321,123,test", + expectedOutput: "198", + recipeConfig: [ + { + "op": "Subtract", + "args": ["Comma"] + }, + ], + }, + { + name: "Subtract - no valid input", + input: "test", + expectedOutput: "NaN", + recipeConfig: [ + { + "op": "Subtract", + "args": ["Comma"] + }, + ], + }, +]);