cyberchef 11.1.0 → 11.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -13,6 +13,17 @@ All major and minor version changes will be documented in this file. Details of
13
13
 
14
14
  ## Details
15
15
 
16
+ ### [11.2.0] - 2026-06-17
17
+ This release includes a security fix ([#2569])
18
+ - Security: Chart operation prototype protection [@C85297] | [#2569]
19
+ - Update website references [@C85297] | [#2566]
20
+ - Fix: Add input validation for XOR Checksum blocksize (#2537) [@dweep-js] | [#2542]
21
+ - Fix: Reverse highlights unwind incorrectly [@kendallgoto] [@C85297] | [#2022]
22
+ - Fix Uint8Array concat crash in Parse IPv4 header [@Zish19] | [#2409]
23
+ - Fix typos and documentation errors (bytes→bits, wrong release link, spelling) [@qa2me] [@GCHQDeveloper581] | [#2404]
24
+ - Add integer check for alphabet size [@heapframe] [@GCHQDeveloper581] | [#2458]
25
+ - fix: validate hexdump width upper bound [@skyswordw] | [#2514]
26
+
16
27
  ### [11.1.0] - 2026-06-13
17
28
  This release includes a security fix ([#2557])
18
29
  - Security: Add fix, and tests, for Lorem Ipsum DoS issue [@GCHQDeveloper581] | [#2557]
@@ -707,6 +718,7 @@ Breaking changes:
707
718
  ## [4.0.0] - 2016-11-28
708
719
  - Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306)
709
720
 
721
+ [11.2.0]: https://github.com/gchq/CyberChef/releases/tag/v11.2.0
710
722
  [11.1.0]: https://github.com/gchq/CyberChef/releases/tag/v11.1.0
711
723
  [11.0.0]: https://github.com/gchq/CyberChef/releases/tag/v11.0.0
712
724
  [10.24.0]: https://github.com/gchq/CyberChef/releases/tag/v10.24.0
@@ -725,7 +737,7 @@ Breaking changes:
725
737
  [10.11.0]: https://github.com/gchq/CyberChef/releases/tag/v10.11.0
726
738
  [10.10.0]: https://github.com/gchq/CyberChef/releases/tag/v10.10.0
727
739
  [10.9.0]: https://github.com/gchq/CyberChef/releases/tag/v10.9.0
728
- [10.8.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0
740
+ [10.8.0]: https://github.com/gchq/CyberChef/releases/tag/v10.8.0
729
741
  [10.7.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0
730
742
  [10.6.0]: https://github.com/gchq/CyberChef/releases/tag/v10.6.0
731
743
  [10.5.0]: https://github.com/gchq/CyberChef/releases/tag/v10.5.0
@@ -1001,6 +1013,11 @@ Breaking changes:
1001
1013
  [@Louis-Ladd]: https://github.com/Louis-Ladd
1002
1014
  [@Blank0120]: https://github.com/Blank0120
1003
1015
  [@zachbowden]: https://github.com/zachbowden
1016
+ [@dweep-js]: https://github.com/dweep-js
1017
+ [@Zish19]: https://github.com/Zish19
1018
+ [@qa2me]: https://github.com/qa2me
1019
+ [@heapframe]: https://github.com/heapframe
1020
+ [@skyswordw]: https://github.com/skyswordw
1004
1021
 
1005
1022
 
1006
1023
  [8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
@@ -1364,4 +1381,12 @@ Breaking changes:
1364
1381
  [#2332]: https://github.com/gchq/CyberChef/pull/2332
1365
1382
  [#2353]: https://github.com/gchq/CyberChef/pull/2353
1366
1383
  [#2351]: https://github.com/gchq/CyberChef/pull/2351
1384
+ [#2569]: https://github.com/gchq/CyberChef/pull/2569
1385
+ [#2566]: https://github.com/gchq/CyberChef/pull/2566
1386
+ [#2542]: https://github.com/gchq/CyberChef/pull/2542
1387
+ [#2022]: https://github.com/gchq/CyberChef/pull/2022
1388
+ [#2409]: https://github.com/gchq/CyberChef/pull/2409
1389
+ [#2404]: https://github.com/gchq/CyberChef/pull/2404
1390
+ [#2458]: https://github.com/gchq/CyberChef/pull/2458
1391
+ [#2514]: https://github.com/gchq/CyberChef/pull/2514
1367
1392
 
package/README.md CHANGED
@@ -12,13 +12,9 @@ CyberChef is a simple, intuitive web app for carrying out all manner of "cyber"
12
12
 
13
13
  The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years.
14
14
 
15
- ## Live demo
15
+ ## Official website
16
16
 
17
- CyberChef is still under active development. As a result, it shouldn't be considered a finished product. There is still testing and bug fixing to do, new features to be added and additional documentation to write. Please contribute!
18
-
19
- Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness.
20
-
21
- [A live demo can be found here][1] - have fun!
17
+ [CyberChef's official website can be found here][1] - have fun!
22
18
 
23
19
  ## Running Locally with Docker
24
20
 
@@ -124,6 +120,11 @@ CyberChef is built to support
124
120
  CyberChef is built to fully support Node.js `v24`. For more information, see the ["Node API" wiki page](https://github.com/gchq/CyberChef/wiki/Node-API)
125
121
 
126
122
 
123
+ ## Security
124
+
125
+ Please see the [CyberChef security policy](./SECURITY.md).
126
+
127
+
127
128
  ## Contributing
128
129
 
129
130
  Contributing a new operation to CyberChef is super easy! The quickstart script will walk you through the process. If you can write basic JavaScript, you can write a CyberChef operation.
package/SECURITY.md CHANGED
@@ -1,11 +1,13 @@
1
1
  # Security Policy
2
2
 
3
- ## Supported Versions
3
+ ## Support
4
4
 
5
5
  CyberChef is supported on a best endeavours basis.
6
6
  Patches will be applied to the latest version rather than retroactively to older versions.
7
7
  To ensure you are using the most secure version of CyberChef, please make sure you have the [latest release](https://github.com/gchq/CyberChef/releases/latest). [The official website](https://gchq.github.io/CyberChef/) is always up to date.
8
8
 
9
+ No guarantee is offered for the correctness or security of CyberChef. In paticular, the security of cryptographic operations should not be relied upon.
10
+
9
11
  ## Reporting a Vulnerability
10
12
 
11
13
  If you discover a vulnerability in CyberChef, please do not publicly disclose it, and do not create a GitHub issue.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyberchef",
3
- "version": "11.1.0",
3
+ "version": "11.2.0",
4
4
  "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
5
5
  "author": "GCHQ <CyberChef@gchq.gov.uk>",
6
6
  "homepage": "https://gchq.github.io/CyberChef",
package/src/core/Chef.mjs CHANGED
@@ -138,6 +138,8 @@ class Chef {
138
138
 
139
139
  if (!highlights) return false;
140
140
 
141
+ if (direction === "reverse") highlights.reverse();
142
+
141
143
  for (let i = 0; i < highlights.length; i++) {
142
144
  // Remove multiple highlights before processing again
143
145
  pos = [pos[0]];
@@ -13314,7 +13314,7 @@
13314
13314
  },
13315
13315
  "Parity Bit": {
13316
13316
  "module": "Default",
13317
- "description": "A parity bit, or check bit, is the simplest form of error detection. It is a bit which is added to a string of bits and represents if the number of 1's in the binary string is an even number or odd number.<br><br>If a delimiter is specified, the parity bit calculation will be performed on each 'block' of the input data, where the blocks are created by slicing the input at each occurence of the delimiter character",
13317
+ "description": "A parity bit, or check bit, is the simplest form of error detection. It is a bit which is added to a string of bits and represents if the number of 1's in the binary string is an even number or odd number.<br><br>If a delimiter is specified, the parity bit calculation will be performed on each 'block' of the input data, where the blocks are created by slicing the input at each occurrence of the delimiter character",
13318
13318
  "infoURL": "https://wikipedia.org/wiki/Parity_bit",
13319
13319
  "inputType": "string",
13320
13320
  "outputType": "string",
@@ -16036,7 +16036,7 @@
16036
16036
  },
16037
16037
  "SHA2": {
16038
16038
  "module": "Crypto",
16039
- "description": "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.",
16039
+ "description": "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bits.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bits.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.",
16040
16040
  "infoURL": "https://wikipedia.org/wiki/SHA-2",
16041
16041
  "inputType": "ArrayBuffer",
16042
16042
  "outputType": "string",
@@ -19396,7 +19396,8 @@
19396
19396
  "name": "Width",
19397
19397
  "type": "number",
19398
19398
  "value": 16,
19399
- "min": 1
19399
+ "min": 1,
19400
+ "max": 65536
19400
19401
  },
19401
19402
  {
19402
19403
  "name": "Upper case hex",
@@ -11,7 +11,7 @@
11
11
  class DishType {
12
12
 
13
13
  /**
14
- * Warn translations dont work without value from bind
14
+ * Warn translations don't work without value from bind
15
15
  */
16
16
  static checkForValue(value) {
17
17
  if (value === undefined) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Custom error type for handling operation that isnt included in node.js API
2
+ * Custom error type for handling operation that isn't included in node.js API
3
3
  *
4
4
  * @author d98762625 [d98762625@gmail.com]
5
5
  * @copyright Crown Copyright 2018
@@ -153,7 +153,7 @@ export function getSeriesValues(input, recordDelimiter, fieldDelimiter, columnHe
153
153
  );
154
154
 
155
155
  let xValues = new Set();
156
- const series = {};
156
+ const series = Object.create(null);
157
157
 
158
158
  values.forEach(row => {
159
159
  const serie = row[0],
@@ -163,14 +163,14 @@ export function getSeriesValues(input, recordDelimiter, fieldDelimiter, columnHe
163
163
  if (Number.isNaN(val)) throw new OperationError("Values must be numbers in base 10.");
164
164
 
165
165
  xValues.add(xVal);
166
- if (typeof series[serie] === "undefined") series[serie] = {};
166
+ if (typeof series[serie] === "undefined") series[serie] = Object.create(null);
167
167
  series[serie][xVal] = val;
168
168
  });
169
169
 
170
170
  xValues = new Array(...xValues);
171
171
 
172
172
  const seriesList = [];
173
- for (const seriesName in series) {
173
+ for (const seriesName of Object.keys(series)) {
174
174
  const serie = series[seriesName];
175
175
  seriesList.push({name: seriesName, data: serie});
176
176
  }
@@ -8,6 +8,7 @@
8
8
 
9
9
  import BigNumber from "bignumber.js";
10
10
  import {toHexFast} from "../lib/Hex.mjs";
11
+ import Utils from "../Utils.mjs";
11
12
 
12
13
  /**
13
14
  * Recursively displays a JSON object as an HTML table
@@ -25,15 +26,16 @@ export function objToTable(obj, nested=false) {
25
26
  <th>Value</th>
26
27
  </tr>`;
27
28
 
28
- for (const key in obj) {
29
- if (typeof obj[key] === "function")
29
+ for (const key of Object.keys(obj)) {
30
+ const value = obj[key];
31
+ if (typeof value === "function")
30
32
  continue;
31
33
 
32
- html += `<tr><td style='word-wrap: break-word'>${key}</td>`;
33
- if (typeof obj[key] === "object")
34
- html += `<td style='padding: 0'>${objToTable(obj[key], true)}</td>`;
34
+ html += `<tr><td style='word-wrap: break-word'>${Utils.escapeHtml(String(key))}</td>`;
35
+ if (value !== null && typeof value === "object")
36
+ html += `<td style='padding: 0'>${objToTable(value, true)}</td>`;
35
37
  else
36
- html += `<td>${obj[key]}</td>`;
38
+ html += `<td>${Utils.escapeHtml(String(value))}</td>`;
37
39
  html += "</tr>";
38
40
  }
39
41
  html += "</table>";
@@ -50,6 +50,14 @@ class GenerateDeBruijnSequence extends Operation {
50
50
  throw new OperationError("Invalid alphabet size, required to be between 2 and 9 (inclusive).");
51
51
  }
52
52
 
53
+ if (!Number.isInteger(k)) {
54
+ throw new OperationError("Invalid alphabet size, required to be integer.");
55
+ }
56
+
57
+ if (!Number.isInteger(n)) {
58
+ throw new OperationError("Invalid key length, required to be integer.");
59
+ }
60
+
53
61
  if (n < 2) {
54
62
  throw new OperationError("Invalid key length, required to be at least 2.");
55
63
  }
@@ -20,7 +20,7 @@ class ParityBit extends Operation {
20
20
 
21
21
  this.name = "Parity Bit";
22
22
  this.module = "Default";
23
- this.description = "A parity bit, or check bit, is the simplest form of error detection. It is a bit which is added to a string of bits and represents if the number of 1's in the binary string is an even number or odd number.<br><br>If a delimiter is specified, the parity bit calculation will be performed on each 'block' of the input data, where the blocks are created by slicing the input at each occurence of the delimiter character";
23
+ this.description = "A parity bit, or check bit, is the simplest form of error detection. It is a bit which is added to a string of bits and represents if the number of 1's in the binary string is an even number or odd number.<br><br>If a delimiter is specified, the parity bit calculation will be performed on each 'block' of the input data, where the blocks are created by slicing the input at each occurrence of the delimiter character";
24
24
  this.infoURL = "https://wikipedia.org/wiki/Parity_bit";
25
25
  this.inputType = "string";
26
26
  this.outputType = "string";
@@ -74,7 +74,7 @@ class ParseIPv4Header extends Operation {
74
74
  checksum = input[10] << 8 | input[11],
75
75
  srcIP = input[12] << 24 | input[13] << 16 | input[14] << 8 | input[15],
76
76
  dstIP = input[16] << 24 | input[17] << 16 | input[18] << 8 | input[19],
77
- checksumHeader = input.slice(0, 10).concat([0, 0]).concat(input.slice(12, 20));
77
+ checksumHeader = [...input.slice(0, 10), 0, 0, ...input.slice(12, 20)];
78
78
  let version = (input[0] >>> 4) & 0x0f,
79
79
  options = [];
80
80
 
@@ -20,7 +20,7 @@ class SHA2 extends Operation {
20
20
 
21
21
  this.name = "SHA2";
22
22
  this.module = "Crypto";
23
- this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.";
23
+ this.description = "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bits.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bits.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul> The message digest algorithm for SHA256 variants consists, by default, of 64 rounds, and for SHA512 variants, it is, by default, 160.";
24
24
  this.infoURL = "https://wikipedia.org/wiki/SHA-2";
25
25
  this.inputType = "ArrayBuffer";
26
26
  this.outputType = "string";
@@ -8,6 +8,8 @@ import Operation from "../Operation.mjs";
8
8
  import Utils from "../Utils.mjs";
9
9
  import OperationError from "../errors/OperationError.mjs";
10
10
 
11
+ const MAX_WIDTH = 65536;
12
+
11
13
  /**
12
14
  * To Hexdump operation
13
15
  */
@@ -30,7 +32,8 @@ class ToHexdump extends Operation {
30
32
  "name": "Width",
31
33
  "type": "number",
32
34
  "value": 16,
33
- "min": 1
35
+ "min": 1,
36
+ "max": MAX_WIDTH
34
37
  },
35
38
  {
36
39
  "name": "Upper case hex",
@@ -63,6 +66,9 @@ class ToHexdump extends Operation {
63
66
  if (length < 1 || Math.round(length) !== length)
64
67
  throw new OperationError("Width must be a positive integer");
65
68
 
69
+ if (length > MAX_WIDTH)
70
+ throw new OperationError(`Width must be no more than ${MAX_WIDTH}`);
71
+
66
72
  const lines = [];
67
73
  for (let i = 0; i < data.length; i += length) {
68
74
  let lineNo = Utils.hex(i, 8);
@@ -7,12 +7,12 @@
7
7
  import Operation from "../Operation.mjs";
8
8
  import Utils from "../Utils.mjs";
9
9
  import { toHex } from "../lib/Hex.mjs";
10
+ import OperationError from "../errors/OperationError.mjs";
10
11
 
11
12
  /**
12
13
  * XOR Checksum operation
13
14
  */
14
15
  class XORChecksum extends Operation {
15
-
16
16
  /**
17
17
  * XORChecksum constructor
18
18
  */
@@ -21,7 +21,8 @@ class XORChecksum extends Operation {
21
21
 
22
22
  this.name = "XOR Checksum";
23
23
  this.module = "Crypto";
24
- this.description = "XOR Checksum splits the input into blocks of a configurable size and performs the XOR operation on these blocks.";
24
+ this.description =
25
+ "XOR Checksum splits the input into blocks of a configurable size and performs the XOR operation on these blocks.";
25
26
  this.infoURL = "https://wikipedia.org/wiki/XOR";
26
27
  this.inputType = "ArrayBuffer";
27
28
  this.outputType = "string";
@@ -29,7 +30,7 @@ class XORChecksum extends Operation {
29
30
  {
30
31
  name: "Blocksize",
31
32
  type: "number",
32
- value: 4
33
+ value: 4,
33
34
  },
34
35
  ];
35
36
  }
@@ -41,6 +42,12 @@ class XORChecksum extends Operation {
41
42
  */
42
43
  run(input, args) {
43
44
  const blocksize = args[0];
45
+
46
+
47
+ if (!Number.isInteger(blocksize) || blocksize <= 0) {
48
+ throw new OperationError("Blocksize must be a positive integer.");
49
+ }
50
+
44
51
  input = new Uint8Array(input);
45
52
 
46
53
  const res = Array(blocksize);
@@ -25,6 +25,7 @@ import "./tests/NodeDish.mjs";
25
25
  import "./tests/Utils.mjs";
26
26
  import "./tests/Categories.mjs";
27
27
  import "./tests/lib/BigIntUtils.mjs";
28
+ import "./tests/lib/ChartsProtocolPrototypePollution.mjs";
28
29
 
29
30
  const testStatus = {
30
31
  allTestsPassing: true,
@@ -0,0 +1,90 @@
1
+ import TestRegister from "../../../lib/TestRegister.mjs";
2
+ import {getSeriesValues} from "../../../../src/core/lib/Charts.mjs";
3
+ import {objToTable} from "../../../../src/core/lib/Protocol.mjs";
4
+ import SeriesChart from "../../../../src/core/operations/SeriesChart.mjs";
5
+ import ParseUDP from "../../../../src/core/operations/ParseUDP.mjs";
6
+ import it from "../../assertionHandler.mjs";
7
+ import assert from "assert";
8
+
9
+ const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
10
+
11
+ TestRegister.addApiTests([
12
+ it("Charts: should not pollute Object.prototype from a __proto__ series name", () => {
13
+ const xVal = "<img src=x onerror=alert(1)>";
14
+ delete Object.prototype[xVal];
15
+
16
+ try {
17
+ const result = getSeriesValues(`__proto__,${xVal},1`, "\n", ",", false);
18
+
19
+ assert.equal(Object.prototype[xVal], undefined);
20
+ assert.deepEqual(result.xValues, [xVal]);
21
+ assert.equal(result.series.length, 1);
22
+ assert.equal(result.series[0].name, "__proto__");
23
+ assert.equal(Object.getPrototypeOf(result.series[0].data), null);
24
+ assert(hasOwn(result.series[0].data, xVal));
25
+ assert.equal(result.series[0].data[xVal], 1);
26
+ } finally {
27
+ delete Object.prototype[xVal];
28
+ }
29
+ }),
30
+
31
+ it("Charts: should keep __proto__ x-axis names as own data keys", () => {
32
+ const result = getSeriesValues("safe,__proto__,1", "\n", ",", false);
33
+
34
+ assert.equal(result.series.length, 1);
35
+ assert.equal(Object.getPrototypeOf(result.series[0].data), null);
36
+ assert(hasOwn(result.series[0].data, "__proto__"));
37
+ assert.equal(result.series[0].data.__proto__, 1);
38
+ }),
39
+
40
+ it("Protocol: should ignore inherited properties when rendering tables", () => {
41
+ const inheritedKey = "<img src=x onerror=alert(1)>";
42
+ delete Object.prototype[inheritedKey];
43
+
44
+ try {
45
+ Object.prototype[inheritedKey] = "polluted";
46
+
47
+ const html = objToTable({safe: "value"});
48
+
49
+ assert(!html.includes(inheritedKey));
50
+ assert(!html.includes("polluted"));
51
+ assert(html.includes("safe"));
52
+ assert(html.includes("value"));
53
+ } finally {
54
+ delete Object.prototype[inheritedKey];
55
+ }
56
+ }),
57
+
58
+ it("Protocol: should escape table keys and scalar values", () => {
59
+ const obj = {
60
+ "<b>field</b>": "<img src=x onerror=alert(1)>",
61
+ };
62
+
63
+ const html = objToTable(obj);
64
+
65
+ assert(!html.includes("<b>field</b>"));
66
+ assert(!html.includes("<img src=x onerror=alert(1)>"));
67
+ assert(html.includes("&lt;b&gt;field&lt;/b&gt;"));
68
+ assert(html.includes("&lt;img src=x onerror=alert(1)&gt;"));
69
+ }),
70
+
71
+ it("Series chart and Parse UDP: should not expose polluted prototype data as HTML", () => {
72
+ const xVal = "<img src=x onerror=alert(document.domain)>";
73
+ delete Object.prototype[xVal];
74
+
75
+ try {
76
+ const chartHtml = new SeriesChart().run(
77
+ `__proto__,${xVal},1`,
78
+ ["Line feed", "Comma", "", 1, "red"]
79
+ );
80
+ assert.equal(Object.prototype[xVal], undefined);
81
+
82
+ const parseUDP = new ParseUDP();
83
+ const tableHtml = parseUDP.present(parseUDP.run(chartHtml, ["Raw"]));
84
+
85
+ assert(!/<img|onerror|alert\(/.test(tableHtml));
86
+ } finally {
87
+ delete Object.prototype[xVal];
88
+ }
89
+ }),
90
+ ]);
@@ -126,6 +126,17 @@ TestRegister.addTests([
126
126
  }
127
127
  ],
128
128
  },
129
+ {
130
+ name: "To Hexdump: Width too large",
131
+ input: "H",
132
+ expectedOutput: "Width must be no more than 65536",
133
+ recipeConfig: [
134
+ {
135
+ op: "To Hexdump",
136
+ args: [155555555555555, false, false, false]
137
+ }
138
+ ],
139
+ },
129
140
  {
130
141
  name: "From Hexdump: xxd",
131
142
  input: `00000000: 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f ................
@@ -19,5 +19,16 @@ TestRegister.addTests([
19
19
  args: ["Hex", "Data (raw)"]
20
20
  }
21
21
  ]
22
+ },
23
+ {
24
+ name: "Parse IPv4 header: regression for Uint8Array.concat crash on truncated raw input",
25
+ input: "\x45\x00\x00\x14\x00\x00\x00\x00\x40\x06\x00\x00",
26
+ expectedOutput: "",
27
+ recipeConfig: [
28
+ {
29
+ op: "Parse IPv4 header",
30
+ args: ["Raw", "Data (raw)"]
31
+ }
32
+ ]
22
33
  }
23
34
  ]);