cyberchef 10.24.0 → 11.1.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.
Files changed (81) hide show
  1. package/.devcontainer/devcontainer.json +1 -1
  2. package/.nvmrc +1 -1
  3. package/CHANGELOG.md +172 -0
  4. package/Dockerfile +2 -2
  5. package/Gruntfile.js +11 -6
  6. package/README.md +6 -4
  7. package/SECURITY.md +8 -18
  8. package/babel.config.js +4 -1
  9. package/package.json +48 -43
  10. package/src/core/ChefWorker.js +1 -1
  11. package/src/core/Recipe.mjs +1 -1
  12. package/src/core/config/Categories.json +6 -0
  13. package/src/core/config/OperationConfig.json +140 -16
  14. package/src/core/config/modules/Default.mjs +8 -0
  15. package/src/core/config/modules/PGP.mjs +2 -0
  16. package/src/core/config/scripts/generateOpsIndex.mjs +63 -0
  17. package/src/core/config/scripts/newOperation.mjs +31 -4
  18. package/src/core/lib/Magic.mjs +1 -1
  19. package/src/core/operations/AESDecrypt.mjs +61 -16
  20. package/src/core/operations/AESEncrypt.mjs +26 -11
  21. package/src/core/operations/BLAKE3.mjs +13 -7
  22. package/src/core/operations/BSONDeserialise.mjs +2 -2
  23. package/src/core/operations/BSONSerialise.mjs +3 -2
  24. package/src/core/operations/Bcrypt.mjs +1 -1
  25. package/src/core/operations/BcryptCompare.mjs +1 -1
  26. package/src/core/operations/DecodeText.mjs +4 -0
  27. package/src/core/operations/EncodeText.mjs +4 -0
  28. package/src/core/operations/EscapeSmartCharacters.mjs +129 -0
  29. package/src/core/operations/FromPunycode.mjs +1 -1
  30. package/src/core/operations/GenerateLoremIpsum.mjs +34 -3
  31. package/src/core/operations/GeneratePGPKeyPair.mjs +8 -7
  32. package/src/core/operations/PGPSign.mjs +83 -0
  33. package/src/core/operations/ParseEthernetFrame.mjs +1 -1
  34. package/src/core/operations/ParseIPv4Header.mjs +1 -1
  35. package/src/core/operations/ParseObjectIDTimestamp.mjs +2 -2
  36. package/src/core/operations/ParseUserAgent.mjs +1 -1
  37. package/src/core/operations/ROR13.mjs +83 -0
  38. package/src/core/operations/RemoveANSIEscapeCodes.mjs +41 -0
  39. package/src/core/operations/SeriesChart.mjs +16 -0
  40. package/src/core/operations/ShowBase64Offsets.mjs +28 -28
  41. package/src/core/operations/ToPunycode.mjs +1 -1
  42. package/src/core/operations/Wrap.mjs +47 -0
  43. package/src/core/operations/index.mjs +10 -0
  44. package/src/node/NodeRecipe.mjs +8 -7
  45. package/src/node/api.mjs +4 -4
  46. package/src/node/index.mjs +25 -0
  47. package/src/web/App.mjs +19 -1
  48. package/src/web/HTMLIngredient.mjs +1 -0
  49. package/src/web/html/index.html +3 -3
  50. package/src/web/index.js +2 -2
  51. package/src/web/static/sitemap.mjs +4 -4
  52. package/src/web/waiters/RecipeWaiter.mjs +9 -1
  53. package/tests/browser/02_ops.js +7 -7
  54. package/tests/browser/03_recipe_load.js +48 -0
  55. package/tests/browser/browserUtils.js +6 -3
  56. package/tests/lib/wasmFetchPolyfill.mjs +31 -0
  57. package/tests/node/consumers/cjs-consumer.js +2 -2
  58. package/tests/node/consumers/esm-consumer.mjs +2 -2
  59. package/tests/node/index.mjs +1 -0
  60. package/tests/node/tests/Categories.mjs +2 -2
  61. package/tests/node/tests/PGP.mjs +69 -0
  62. package/tests/node/tests/nodeApi.mjs +55 -58
  63. package/tests/node/tests/operations.mjs +41 -2
  64. package/tests/operations/index.mjs +72 -66
  65. package/tests/operations/tests/BLAKE3.mjs +18 -0
  66. package/tests/operations/tests/Base64.mjs +11 -0
  67. package/tests/operations/tests/CharEnc.mjs +26 -0
  68. package/tests/operations/tests/Charts.mjs +11 -0
  69. package/tests/operations/tests/Crypt.mjs +288 -62
  70. package/tests/operations/tests/EscapeSmartCharacters.mjs +132 -0
  71. package/tests/operations/tests/FlaskSession.mjs +11 -8
  72. package/tests/operations/tests/GenerateLoremIpsum.mjs +80 -0
  73. package/tests/operations/tests/IPv6Transition.mjs +4 -4
  74. package/tests/operations/tests/PGP.mjs +178 -154
  75. package/tests/operations/tests/ParseEthernetFrame.mjs +11 -0
  76. package/tests/operations/tests/ParseIPv4Header.mjs +23 -0
  77. package/tests/operations/tests/ParseX509CRL.mjs +16 -16
  78. package/tests/operations/tests/ROR13.mjs +45 -0
  79. package/tests/operations/tests/Register.mjs +3 -1
  80. package/tests/operations/tests/RemoveANSIEscapeCodes.mjs +62 -0
  81. package/tests/operations/tests/Wrap.mjs +44 -0
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @author Louis-Ladd [lewisharshman1@gmail.com]
3
+ * @copyright Crown Copyright 2025
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+
9
+ /**
10
+ * Remove ANSI Escape Codes operation
11
+ */
12
+ class RemoveANSIEscapeCodes extends Operation {
13
+
14
+ /**
15
+ * RemoveANSIEscapeCodes constructor
16
+ */
17
+ constructor() {
18
+ super();
19
+
20
+ this.name = "Remove ANSI Escape Codes";
21
+ this.module = "Default";
22
+ this.description = "Removes ANSI Escape Codes.";
23
+ this.infoURL = "https://wikipedia.org/wiki/ANSI_escape_code";
24
+ this.inputType = "string";
25
+ this.outputType = "string";
26
+ this.args = [];
27
+ }
28
+
29
+ /**
30
+ * @param {string} input
31
+ * @param {Object[]} args
32
+ * @returns {string}
33
+ */
34
+ run(input, args) {
35
+ const ansiRegex = /\x1B\[[0-?]*[ -/]*[@-~]/g;
36
+ return input.replace(ansiRegex, "");
37
+ }
38
+
39
+ }
40
+
41
+ export default RemoveANSIEscapeCodes;
@@ -15,6 +15,20 @@ import Utils from "../Utils.mjs";
15
15
  const d3 = d3temp.default ? d3temp.default : d3temp;
16
16
  const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp;
17
17
 
18
+ /**
19
+ * Removes D3's internal bound data from a nodom tree before serialization.
20
+ * nodom serializes enumerable expando properties such as __data__ as attributes,
21
+ * so leaving them on attacker-controlled values can create executable markup.
22
+ *
23
+ * @param {Object} node
24
+ */
25
+ function clearD3BoundData(node) {
26
+ delete node.__data__;
27
+
28
+ if (!node.childNodes) return;
29
+ node.childNodes.forEach(clearD3BoundData);
30
+ }
31
+
18
32
  /**
19
33
  * Series chart operation
20
34
  */
@@ -222,6 +236,8 @@ class SeriesChart extends Operation {
222
236
  .text(serie.name);
223
237
  });
224
238
 
239
+ clearD3BoundData(svg.node());
240
+
225
241
  return svg._groups[0][0].outerHTML;
226
242
  }
227
243
 
@@ -77,84 +77,84 @@ class ShowBase64Offsets extends Operation {
77
77
  staticSection = offset0.slice(0, -3);
78
78
  offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
79
79
  Utils.escapeHtml(fromBase64(staticSection, alphabet).slice(0, -2)) + "'>" +
80
- staticSection + "</span>" +
81
- "<span class='hl5'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
82
- "<span class='hl3'>" + offset0.substr(offset0.length - 2) + "</span>";
80
+ Utils.escapeHtml(staticSection) + "</span>" +
81
+ "<span class='hl5'>" + Utils.escapeHtml(offset0.substr(offset0.length - 3, 1)) + "</span>" +
82
+ "<span class='hl3'>" + Utils.escapeHtml(offset0.substr(offset0.length - 2)) + "</span>";
83
83
  } else if (len0 % 4 === 3) {
84
84
  staticSection = offset0.slice(0, -2);
85
85
  offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
86
86
  Utils.escapeHtml(fromBase64(staticSection, alphabet).slice(0, -1)) + "'>" +
87
- staticSection + "</span>" +
88
- "<span class='hl5'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
89
- "<span class='hl3'>" + offset0.substr(offset0.length - 1) + "</span>";
87
+ Utils.escapeHtml(staticSection) + "</span>" +
88
+ "<span class='hl5'>" + Utils.escapeHtml(offset0.substr(offset0.length - 2, 1)) + "</span>" +
89
+ "<span class='hl3'>" + Utils.escapeHtml(offset0.substr(offset0.length - 1)) + "</span>";
90
90
  } else {
91
91
  staticSection = offset0;
92
92
  offset0 = "<span data-toggle='tooltip' data-placement='top' title='" +
93
93
  Utils.escapeHtml(fromBase64(staticSection, alphabet)) + "'>" +
94
- staticSection + "</span>";
94
+ Utils.escapeHtml(staticSection) + "</span>";
95
95
  }
96
96
 
97
97
  if (!showVariable) {
98
- offset0 = staticSection;
98
+ offset0 = Utils.escapeHtml(staticSection);
99
99
  }
100
100
 
101
101
 
102
102
  // Highlight offset 1
103
- padding = "<span class='hl3'>" + offset1.substr(0, 1) + "</span>" +
104
- "<span class='hl5'>" + offset1.substr(1, 1) + "</span>";
103
+ padding = "<span class='hl3'>" + Utils.escapeHtml(offset1.substr(0, 1)) + "</span>" +
104
+ "<span class='hl5'>" + Utils.escapeHtml(offset1.substr(1, 1)) + "</span>";
105
105
  offset1 = offset1.substr(2);
106
106
  if (len1 % 4 === 2) {
107
107
  staticSection = offset1.slice(0, -3);
108
108
  offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
109
109
  Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1, -2)) + "'>" +
110
- staticSection + "</span>" +
111
- "<span class='hl5'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
112
- "<span class='hl3'>" + offset1.substr(offset1.length - 2) + "</span>";
110
+ Utils.escapeHtml(staticSection) + "</span>" +
111
+ "<span class='hl5'>" + Utils.escapeHtml(offset1.substr(offset1.length - 3, 1)) + "</span>" +
112
+ "<span class='hl3'>" + Utils.escapeHtml(offset1.substr(offset1.length - 2)) + "</span>";
113
113
  } else if (len1 % 4 === 3) {
114
114
  staticSection = offset1.slice(0, -2);
115
115
  offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
116
116
  Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1, -1)) + "'>" +
117
- staticSection + "</span>" +
118
- "<span class='hl5'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
119
- "<span class='hl3'>" + offset1.substr(offset1.length - 1) + "</span>";
117
+ Utils.escapeHtml(staticSection) + "</span>" +
118
+ "<span class='hl5'>" + Utils.escapeHtml(offset1.substr(offset1.length - 2, 1)) + "</span>" +
119
+ "<span class='hl3'>" + Utils.escapeHtml(offset1.substr(offset1.length - 1)) + "</span>";
120
120
  } else {
121
121
  staticSection = offset1;
122
122
  offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
123
123
  Utils.escapeHtml(fromBase64("AA" + staticSection, alphabet).slice(1)) + "'>" +
124
- staticSection + "</span>";
124
+ Utils.escapeHtml(staticSection) + "</span>";
125
125
  }
126
126
 
127
127
  if (!showVariable) {
128
- offset1 = staticSection;
128
+ offset1 = Utils.escapeHtml(staticSection);
129
129
  }
130
130
 
131
131
  // Highlight offset 2
132
- padding = "<span class='hl3'>" + offset2.substr(0, 2) + "</span>" +
133
- "<span class='hl5'>" + offset2.substr(2, 1) + "</span>";
132
+ padding = "<span class='hl3'>" + Utils.escapeHtml(offset2.substr(0, 2)) + "</span>" +
133
+ "<span class='hl5'>" + Utils.escapeHtml(offset2.substr(2, 1)) + "</span>";
134
134
  offset2 = offset2.substr(3);
135
135
  if (len2 % 4 === 2) {
136
136
  staticSection = offset2.slice(0, -3);
137
137
  offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
138
138
  Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
139
- staticSection + "</span>" +
140
- "<span class='hl5'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
141
- "<span class='hl3'>" + offset2.substr(offset2.length - 2) + "</span>";
139
+ Utils.escapeHtml(staticSection) + "</span>" +
140
+ "<span class='hl5'>" + Utils.escapeHtml(offset2.substr(offset2.length - 3, 1)) + "</span>" +
141
+ "<span class='hl3'>" + Utils.escapeHtml(offset2.substr(offset2.length - 2)) + "</span>";
142
142
  } else if (len2 % 4 === 3) {
143
143
  staticSection = offset2.slice(0, -2);
144
144
  offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
145
145
  Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2, -2)) + "'>" +
146
- staticSection + "</span>" +
147
- "<span class='hl5'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
148
- "<span class='hl3'>" + offset2.substr(offset2.length - 1) + "</span>";
146
+ Utils.escapeHtml(staticSection) + "</span>" +
147
+ "<span class='hl5'>" + Utils.escapeHtml(offset2.substr(offset2.length - 2, 1)) + "</span>" +
148
+ "<span class='hl3'>" + Utils.escapeHtml(offset2.substr(offset2.length - 1)) + "</span>";
149
149
  } else {
150
150
  staticSection = offset2;
151
151
  offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" +
152
152
  Utils.escapeHtml(fromBase64("AAA" + staticSection, alphabet).slice(2)) + "'>" +
153
- staticSection + "</span>";
153
+ Utils.escapeHtml(staticSection) + "</span>";
154
154
  }
155
155
 
156
156
  if (!showVariable) {
157
- offset2 = staticSection;
157
+ offset2 = Utils.escapeHtml(staticSection);
158
158
  }
159
159
 
160
160
  return (showVariable ? "Characters highlighted in <span class='hl5'>green</span> could change if the input is surrounded by more data." +
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import Operation from "../Operation.mjs";
8
- import punycode from "punycode";
8
+ import punycode from "punycode.js";
9
9
 
10
10
  /**
11
11
  * To Punycode operation
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @author 0xff1ce [github.com/0xff1ce]
3
+ * @copyright Crown Copyright 2024
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ import Operation from "../Operation.mjs";
8
+
9
+ /**
10
+ * Wrap operation
11
+ */
12
+ class Wrap extends Operation {
13
+
14
+ /**
15
+ * Wrap constructor
16
+ */
17
+ constructor() {
18
+ super();
19
+
20
+ this.name = "Wrap";
21
+ this.module = "Default";
22
+ this.description = "Wraps the input text at a specified number of characters per line.";
23
+ this.inputType = "string";
24
+ this.outputType = "string";
25
+ this.args = [
26
+ {
27
+ "name": "Line Width",
28
+ "type": "number",
29
+ "value": 64,
30
+ },
31
+ ];
32
+ }
33
+
34
+ /**
35
+ * @param {string} input
36
+ * @param {Object[]} args
37
+ * @returns {string}
38
+ */
39
+ run(input, args) {
40
+ if (!input) return ""; // Handle empty input
41
+ const lineWidth = args[0];
42
+ const regex = new RegExp(`.{1,${lineWidth}}`, "g");
43
+ return input.match(regex).join("\n");
44
+ }
45
+ }
46
+
47
+ export default Wrap;
@@ -114,6 +114,7 @@ import EncodeNetBIOSName from "./EncodeNetBIOSName.mjs";
114
114
  import EncodeText from "./EncodeText.mjs";
115
115
  import Enigma from "./Enigma.mjs";
116
116
  import Entropy from "./Entropy.mjs";
117
+ import EscapeSmartCharacters from "./EscapeSmartCharacters.mjs";
117
118
  import EscapeString from "./EscapeString.mjs";
118
119
  import EscapeUnicodeCharacters from "./EscapeUnicodeCharacters.mjs";
119
120
  import ExpandAlphabetRange from "./ExpandAlphabetRange.mjs";
@@ -283,6 +284,7 @@ import PGPDecrypt from "./PGPDecrypt.mjs";
283
284
  import PGPDecryptAndVerify from "./PGPDecryptAndVerify.mjs";
284
285
  import PGPEncrypt from "./PGPEncrypt.mjs";
285
286
  import PGPEncryptAndSign from "./PGPEncryptAndSign.mjs";
287
+ import PGPSign from "./PGPSign.mjs";
286
288
  import PGPVerify from "./PGPVerify.mjs";
287
289
  import PHPDeserialize from "./PHPDeserialize.mjs";
288
290
  import PHPSerialize from "./PHPSerialize.mjs";
@@ -325,6 +327,7 @@ import RC4Drop from "./RC4Drop.mjs";
325
327
  import RC6Decrypt from "./RC6Decrypt.mjs";
326
328
  import RC6Encrypt from "./RC6Encrypt.mjs";
327
329
  import RIPEMD from "./RIPEMD.mjs";
330
+ import ROR13 from "./ROR13.mjs";
328
331
  import ROT13 from "./ROT13.mjs";
329
332
  import ROT13BruteForce from "./ROT13BruteForce.mjs";
330
333
  import ROT47 from "./ROT47.mjs";
@@ -342,6 +345,7 @@ import RawDeflate from "./RawDeflate.mjs";
342
345
  import RawInflate from "./RawInflate.mjs";
343
346
  import Register from "./Register.mjs";
344
347
  import RegularExpression from "./RegularExpression.mjs";
348
+ import RemoveANSIEscapeCodes from "./RemoveANSIEscapeCodes.mjs";
345
349
  import RemoveDiacritics from "./RemoveDiacritics.mjs";
346
350
  import RemoveEXIF from "./RemoveEXIF.mjs";
347
351
  import RemoveLineNumbers from "./RemoveLineNumbers.mjs";
@@ -466,6 +470,7 @@ import VigenèreDecode from "./VigenèreDecode.mjs";
466
470
  import VigenèreEncode from "./VigenèreEncode.mjs";
467
471
  import Whirlpool from "./Whirlpool.mjs";
468
472
  import WindowsFiletimeToUNIXTimestamp from "./WindowsFiletimeToUNIXTimestamp.mjs";
473
+ import Wrap from "./Wrap.mjs";
469
474
  import XKCDRandomNumber from "./XKCDRandomNumber.mjs";
470
475
  import XMLBeautify from "./XMLBeautify.mjs";
471
476
  import XMLMinify from "./XMLMinify.mjs";
@@ -592,6 +597,7 @@ export {
592
597
  EncodeText,
593
598
  Enigma,
594
599
  Entropy,
600
+ EscapeSmartCharacters,
595
601
  EscapeString,
596
602
  EscapeUnicodeCharacters,
597
603
  ExpandAlphabetRange,
@@ -761,6 +767,7 @@ export {
761
767
  PGPDecryptAndVerify,
762
768
  PGPEncrypt,
763
769
  PGPEncryptAndSign,
770
+ PGPSign,
764
771
  PGPVerify,
765
772
  PHPDeserialize,
766
773
  PHPSerialize,
@@ -803,6 +810,7 @@ export {
803
810
  RC6Decrypt,
804
811
  RC6Encrypt,
805
812
  RIPEMD,
813
+ ROR13,
806
814
  ROT13,
807
815
  ROT13BruteForce,
808
816
  ROT47,
@@ -820,6 +828,7 @@ export {
820
828
  RawInflate,
821
829
  Register,
822
830
  RegularExpression,
831
+ RemoveANSIEscapeCodes,
823
832
  RemoveDiacritics,
824
833
  RemoveEXIF,
825
834
  RemoveLineNumbers,
@@ -944,6 +953,7 @@ export {
944
953
  VigenèreEncode,
945
954
  Whirlpool,
946
955
  WindowsFiletimeToUNIXTimestamp,
956
+ Wrap,
947
957
  XKCDRandomNumber,
948
958
  XMLBeautify,
949
959
  XMLMinify,
@@ -88,16 +88,17 @@ class NodeRecipe {
88
88
  * @param {NodeDish} dish
89
89
  * @returns {NodeDish}
90
90
  */
91
- execute(dish) {
92
- return this.opList.reduce((prev, curr) => {
93
- // CASE where opList item is op and args
91
+ async execute(dish) {
92
+ let prev = dish;
93
+ for (const curr of this.opList) {
94
94
  if (Object.prototype.hasOwnProperty.call(curr, "op") &&
95
95
  Object.prototype.hasOwnProperty.call(curr, "args")) {
96
- return curr.op(prev, curr.args);
96
+ prev = await curr.op(prev, curr.args);
97
+ } else {
98
+ prev = await curr(prev);
97
99
  }
98
- // CASE opList item is just op.
99
- return curr(prev);
100
- }, dish);
100
+ }
101
+ return prev;
101
102
  }
102
103
  }
103
104
 
package/src/node/api.mjs CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  import NodeDish from "./NodeDish.mjs";
12
12
  import NodeRecipe from "./NodeRecipe.mjs";
13
- import OperationConfig from "../core/config/OperationConfig.json" assert {type: "json"};
13
+ import OperationConfig from "../core/config/OperationConfig.json" with { type: "json" };
14
14
  import { sanitise, removeSubheadingsFromArray, sentenceToCamelCase } from "./apiUtils.mjs";
15
15
  import ExcludedOperationError from "../core/errors/ExcludedOperationError.mjs";
16
16
 
@@ -324,10 +324,10 @@ export function help(input) {
324
324
  * @returns {NodeDish} of the result
325
325
  * @throws {TypeError} if invalid recipe given.
326
326
  */
327
- export function bake(input, recipeConfig) {
328
- const recipe = new NodeRecipe(recipeConfig);
327
+ export async function bake(input, recipeConfig) {
328
+ const recipe = new NodeRecipe(recipeConfig);
329
329
  const dish = ensureIsDish(input);
330
- return recipe.execute(dish);
330
+ return await recipe.execute(dish);
331
331
  }
332
332
 
333
333
 
@@ -122,6 +122,7 @@ import {
122
122
  EncodeText as core_EncodeText,
123
123
  Enigma as core_Enigma,
124
124
  Entropy as core_Entropy,
125
+ EscapeSmartCharacters as core_EscapeSmartCharacters,
125
126
  EscapeString as core_EscapeString,
126
127
  EscapeUnicodeCharacters as core_EscapeUnicodeCharacters,
127
128
  ExpandAlphabetRange as core_ExpandAlphabetRange,
@@ -284,6 +285,7 @@ import {
284
285
  PGPDecryptAndVerify as core_PGPDecryptAndVerify,
285
286
  PGPEncrypt as core_PGPEncrypt,
286
287
  PGPEncryptAndSign as core_PGPEncryptAndSign,
288
+ PGPSign as core_PGPSign,
287
289
  PGPVerify as core_PGPVerify,
288
290
  PHPDeserialize as core_PHPDeserialize,
289
291
  PHPSerialize as core_PHPSerialize,
@@ -326,6 +328,7 @@ import {
326
328
  RC6Decrypt as core_RC6Decrypt,
327
329
  RC6Encrypt as core_RC6Encrypt,
328
330
  RIPEMD as core_RIPEMD,
331
+ ROR13 as core_ROR13,
329
332
  ROT13 as core_ROT13,
330
333
  ROT13BruteForce as core_ROT13BruteForce,
331
334
  ROT47 as core_ROT47,
@@ -343,6 +346,7 @@ import {
343
346
  RawInflate as core_RawInflate,
344
347
  Register as core_Register,
345
348
  RegularExpression as core_RegularExpression,
349
+ RemoveANSIEscapeCodes as core_RemoveANSIEscapeCodes,
346
350
  RemoveDiacritics as core_RemoveDiacritics,
347
351
  RemoveEXIF as core_RemoveEXIF,
348
352
  RemoveLineNumbers as core_RemoveLineNumbers,
@@ -466,6 +470,7 @@ import {
466
470
  VigenèreEncode as core_VigenèreEncode,
467
471
  Whirlpool as core_Whirlpool,
468
472
  WindowsFiletimeToUNIXTimestamp as core_WindowsFiletimeToUNIXTimestamp,
473
+ Wrap as core_Wrap,
469
474
  XKCDRandomNumber as core_XKCDRandomNumber,
470
475
  XMLBeautify as core_XMLBeautify,
471
476
  XMLMinify as core_XMLMinify,
@@ -600,6 +605,7 @@ function generateChef() {
600
605
  "encodeText": _wrap(core_EncodeText),
601
606
  "enigma": _wrap(core_Enigma),
602
607
  "entropy": _wrap(core_Entropy),
608
+ "escapeSmartCharacters": _wrap(core_EscapeSmartCharacters),
603
609
  "escapeString": _wrap(core_EscapeString),
604
610
  "escapeUnicodeCharacters": _wrap(core_EscapeUnicodeCharacters),
605
611
  "expandAlphabetRange": _wrap(core_ExpandAlphabetRange),
@@ -762,6 +768,7 @@ function generateChef() {
762
768
  "PGPDecryptAndVerify": _wrap(core_PGPDecryptAndVerify),
763
769
  "PGPEncrypt": _wrap(core_PGPEncrypt),
764
770
  "PGPEncryptAndSign": _wrap(core_PGPEncryptAndSign),
771
+ "PGPSign": _wrap(core_PGPSign),
765
772
  "PGPVerify": _wrap(core_PGPVerify),
766
773
  "PHPDeserialize": _wrap(core_PHPDeserialize),
767
774
  "PHPSerialize": _wrap(core_PHPSerialize),
@@ -804,6 +811,7 @@ function generateChef() {
804
811
  "RC6Decrypt": _wrap(core_RC6Decrypt),
805
812
  "RC6Encrypt": _wrap(core_RC6Encrypt),
806
813
  "RIPEMD": _wrap(core_RIPEMD),
814
+ "ROR13": _wrap(core_ROR13),
807
815
  "ROT13": _wrap(core_ROT13),
808
816
  "ROT13BruteForce": _wrap(core_ROT13BruteForce),
809
817
  "ROT47": _wrap(core_ROT47),
@@ -821,6 +829,7 @@ function generateChef() {
821
829
  "rawInflate": _wrap(core_RawInflate),
822
830
  "register": _wrap(core_Register),
823
831
  "regularExpression": _wrap(core_RegularExpression),
832
+ "removeANSIEscapeCodes": _wrap(core_RemoveANSIEscapeCodes),
824
833
  "removeDiacritics": _wrap(core_RemoveDiacritics),
825
834
  "removeEXIF": _wrap(core_RemoveEXIF),
826
835
  "removeLineNumbers": _wrap(core_RemoveLineNumbers),
@@ -944,6 +953,7 @@ function generateChef() {
944
953
  "vigenèreEncode": _wrap(core_VigenèreEncode),
945
954
  "whirlpool": _wrap(core_Whirlpool),
946
955
  "windowsFiletimeToUNIXTimestamp": _wrap(core_WindowsFiletimeToUNIXTimestamp),
956
+ "wrap": _wrap(core_Wrap),
947
957
  "XKCDRandomNumber": _wrap(core_XKCDRandomNumber),
948
958
  "XMLBeautify": _wrap(core_XMLBeautify),
949
959
  "XMLMinify": _wrap(core_XMLMinify),
@@ -1088,6 +1098,7 @@ const encodeNetBIOSName = chef.encodeNetBIOSName;
1088
1098
  const encodeText = chef.encodeText;
1089
1099
  const enigma = chef.enigma;
1090
1100
  const entropy = chef.entropy;
1101
+ const escapeSmartCharacters = chef.escapeSmartCharacters;
1091
1102
  const escapeString = chef.escapeString;
1092
1103
  const escapeUnicodeCharacters = chef.escapeUnicodeCharacters;
1093
1104
  const expandAlphabetRange = chef.expandAlphabetRange;
@@ -1257,6 +1268,7 @@ const PGPDecrypt = chef.PGPDecrypt;
1257
1268
  const PGPDecryptAndVerify = chef.PGPDecryptAndVerify;
1258
1269
  const PGPEncrypt = chef.PGPEncrypt;
1259
1270
  const PGPEncryptAndSign = chef.PGPEncryptAndSign;
1271
+ const PGPSign = chef.PGPSign;
1260
1272
  const PGPVerify = chef.PGPVerify;
1261
1273
  const PHPDeserialize = chef.PHPDeserialize;
1262
1274
  const PHPSerialize = chef.PHPSerialize;
@@ -1299,6 +1311,7 @@ const RC4Drop = chef.RC4Drop;
1299
1311
  const RC6Decrypt = chef.RC6Decrypt;
1300
1312
  const RC6Encrypt = chef.RC6Encrypt;
1301
1313
  const RIPEMD = chef.RIPEMD;
1314
+ const ROR13 = chef.ROR13;
1302
1315
  const ROT13 = chef.ROT13;
1303
1316
  const ROT13BruteForce = chef.ROT13BruteForce;
1304
1317
  const ROT47 = chef.ROT47;
@@ -1316,6 +1329,7 @@ const rawDeflate = chef.rawDeflate;
1316
1329
  const rawInflate = chef.rawInflate;
1317
1330
  const register = chef.register;
1318
1331
  const regularExpression = chef.regularExpression;
1332
+ const removeANSIEscapeCodes = chef.removeANSIEscapeCodes;
1319
1333
  const removeDiacritics = chef.removeDiacritics;
1320
1334
  const removeEXIF = chef.removeEXIF;
1321
1335
  const removeLineNumbers = chef.removeLineNumbers;
@@ -1440,6 +1454,7 @@ const vigenèreDecode = chef.vigenèreDecode;
1440
1454
  const vigenèreEncode = chef.vigenèreEncode;
1441
1455
  const whirlpool = chef.whirlpool;
1442
1456
  const windowsFiletimeToUNIXTimestamp = chef.windowsFiletimeToUNIXTimestamp;
1457
+ const wrap = chef.wrap;
1443
1458
  const XKCDRandomNumber = chef.XKCDRandomNumber;
1444
1459
  const XMLBeautify = chef.XMLBeautify;
1445
1460
  const XMLMinify = chef.XMLMinify;
@@ -1568,6 +1583,7 @@ const operations = [
1568
1583
  encodeText,
1569
1584
  enigma,
1570
1585
  entropy,
1586
+ escapeSmartCharacters,
1571
1587
  escapeString,
1572
1588
  escapeUnicodeCharacters,
1573
1589
  expandAlphabetRange,
@@ -1737,6 +1753,7 @@ const operations = [
1737
1753
  PGPDecryptAndVerify,
1738
1754
  PGPEncrypt,
1739
1755
  PGPEncryptAndSign,
1756
+ PGPSign,
1740
1757
  PGPVerify,
1741
1758
  PHPDeserialize,
1742
1759
  PHPSerialize,
@@ -1779,6 +1796,7 @@ const operations = [
1779
1796
  RC6Decrypt,
1780
1797
  RC6Encrypt,
1781
1798
  RIPEMD,
1799
+ ROR13,
1782
1800
  ROT13,
1783
1801
  ROT13BruteForce,
1784
1802
  ROT47,
@@ -1796,6 +1814,7 @@ const operations = [
1796
1814
  rawInflate,
1797
1815
  register,
1798
1816
  regularExpression,
1817
+ removeANSIEscapeCodes,
1799
1818
  removeDiacritics,
1800
1819
  removeEXIF,
1801
1820
  removeLineNumbers,
@@ -1920,6 +1939,7 @@ const operations = [
1920
1939
  vigenèreEncode,
1921
1940
  whirlpool,
1922
1941
  windowsFiletimeToUNIXTimestamp,
1942
+ wrap,
1923
1943
  XKCDRandomNumber,
1924
1944
  XMLBeautify,
1925
1945
  XMLMinify,
@@ -2052,6 +2072,7 @@ export {
2052
2072
  encodeText,
2053
2073
  enigma,
2054
2074
  entropy,
2075
+ escapeSmartCharacters,
2055
2076
  escapeString,
2056
2077
  escapeUnicodeCharacters,
2057
2078
  expandAlphabetRange,
@@ -2221,6 +2242,7 @@ export {
2221
2242
  PGPDecryptAndVerify,
2222
2243
  PGPEncrypt,
2223
2244
  PGPEncryptAndSign,
2245
+ PGPSign,
2224
2246
  PGPVerify,
2225
2247
  PHPDeserialize,
2226
2248
  PHPSerialize,
@@ -2263,6 +2285,7 @@ export {
2263
2285
  RC6Decrypt,
2264
2286
  RC6Encrypt,
2265
2287
  RIPEMD,
2288
+ ROR13,
2266
2289
  ROT13,
2267
2290
  ROT13BruteForce,
2268
2291
  ROT47,
@@ -2280,6 +2303,7 @@ export {
2280
2303
  rawInflate,
2281
2304
  register,
2282
2305
  regularExpression,
2306
+ removeANSIEscapeCodes,
2283
2307
  removeDiacritics,
2284
2308
  removeEXIF,
2285
2309
  removeLineNumbers,
@@ -2404,6 +2428,7 @@ export {
2404
2428
  vigenèreEncode,
2405
2429
  whirlpool,
2406
2430
  windowsFiletimeToUNIXTimestamp,
2431
+ wrap,
2407
2432
  XKCDRandomNumber,
2408
2433
  XMLBeautify,
2409
2434
  XMLMinify,
package/src/web/App.mjs CHANGED
@@ -42,6 +42,14 @@ class App {
42
42
  this.progress = 0;
43
43
  this.ingId = 0;
44
44
 
45
+ // stateChangeId increments on every statechange dispatch; bakeStateId records
46
+ // the stateChangeId captured when the most recent bake started. autoBake uses
47
+ // these to decide whether the output is genuinely stale, so a debounced
48
+ // autoBake firing shortly after a manual bake doesn't clobber the bake's
49
+ // hideStaleIndicator with a redundant showStaleIndicator.
50
+ this.stateChangeId = 0;
51
+ this.bakeStateId = -1;
52
+
45
53
  this.appLoaded = false;
46
54
  this.workerLoaded = false;
47
55
  this.waitersLoaded = false;
@@ -136,6 +144,9 @@ class App {
136
144
  bake(step=false) {
137
145
  if (this.baking) return;
138
146
 
147
+ // Record which state version this bake is covering.
148
+ this.bakeStateId = this.stateChangeId;
149
+
139
150
  // Reset attemptHighlight flag
140
151
  this.options.attemptHighlight = true;
141
152
 
@@ -166,7 +177,10 @@ class App {
166
177
  nums: [this.manager.tabs.getActiveTab("input")],
167
178
  step: false
168
179
  });
169
- } else {
180
+ } else if (this.bakeStateId < this.stateChangeId) {
181
+ // Only show stale-indicator if the most recent bake didn't cover the
182
+ // current state. Without this guard, a debounced autoBake firing after
183
+ // a manual bake completed would re-show the indicator on fresh output.
170
184
  this.manager.controls.showStaleIndicator();
171
185
  }
172
186
  }
@@ -768,6 +782,10 @@ class App {
768
782
  * @param {event} e
769
783
  */
770
784
  stateChange(e) {
785
+ // Bump the state-change counter synchronously so a manual bake invoked between
786
+ // here and the debounced autoBake firing can record it via bakeStateId.
787
+ this.stateChangeId++;
788
+
771
789
  debounce(function() {
772
790
  this.progress = 0;
773
791
  this.autoBake();
@@ -166,6 +166,7 @@ class HTMLIngredient {
166
166
  id="${this.id}"
167
167
  tabindex="${this.tabIndex}"
168
168
  arg-name="${this.name}"
169
+ data-target="${this.target}"
169
170
  ${this.disabled ? "disabled" : ""}>`;
170
171
  for (i = 0; i < this.value.length; i++) {
171
172
  if ((m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) {
@@ -868,15 +868,15 @@
868
868
  Be aware that the standalone version will never update itself, meaning it will not receive bug fixes or new features until you re-download newer versions manually.
869
869
  </p>
870
870
 
871
- <h6>CyberChef v<%= htmlWebpackPlugin.options.version %></h6>
871
+ <h6>CyberChef <%= htmlWebpackPlugin.options.version %></h6>
872
872
  <ul>
873
873
  <li>Build time: <%= htmlWebpackPlugin.options.compileTime %></li>
874
- <li>The changelog for this version can be viewed <a href="https://github.com/gchq/CyberChef/blob/v<%= htmlWebpackPlugin.options.version %>/CHANGELOG.md">here</a></li>
874
+ <li>The changelog for this version can be viewed <a href="https://github.com/gchq/CyberChef/blob/v<%= htmlWebpackPlugin.options.latestReleaseVersion %>/CHANGELOG.md">here</a></li>
875
875
  <li>&copy; Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %></li>
876
876
  <li>Released under the Apache Licence, Version 2.0</li>
877
877
  <li>SHA256 hash: DOWNLOAD_HASH_PLACEHOLDER</li>
878
878
  </ul>
879
- <a href="CyberChef_v<%= htmlWebpackPlugin.options.version %>.zip" download class="btn btn-outline-primary">Download ZIP file</a>
879
+ <a href="<%= htmlWebpackPlugin.options.downloadZipFilename %>" download class="btn btn-outline-primary">Download ZIP file</a>
880
880
  </div>
881
881
  <div class="modal-footer">
882
882
  <button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button>
package/src/web/index.js CHANGED
@@ -17,8 +17,8 @@ import * as CanvasComponents from "../core/lib/CanvasComponents.mjs";
17
17
 
18
18
  // CyberChef
19
19
  import App from "./App.mjs";
20
- import Categories from "../core/config/Categories.json" assert {type: "json"};
21
- import OperationConfig from "../core/config/OperationConfig.json" assert {type: "json"};
20
+ import Categories from "../core/config/Categories.json" with { type: "json" };
21
+ import OperationConfig from "../core/config/OperationConfig.json" with { type: "json" };
22
22
 
23
23
 
24
24
  /**