Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
7830bac871
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@ -25,12 +25,8 @@ updates:
|
|||||||
# see issue #2214 for rationale for each of these
|
# see issue #2214 for rationale for each of these
|
||||||
- dependency-name: '@xmldom/xmldom'
|
- dependency-name: '@xmldom/xmldom'
|
||||||
versions: [ '>=0.9.0' ]
|
versions: [ '>=0.9.0' ]
|
||||||
- dependency-name: 'bcryptjs'
|
|
||||||
versions: [ '>=3.0.0' ]
|
|
||||||
- dependency-name: 'bootstrap'
|
- dependency-name: 'bootstrap'
|
||||||
versions: [ '>=5.0.0' ]
|
versions: [ '>=5.0.0' ]
|
||||||
- dependency-name: 'bson'
|
|
||||||
versions: [ '>=5.0.0' ]
|
|
||||||
- dependency-name: 'cbor'
|
- dependency-name: 'cbor'
|
||||||
versions: [ '>=10.0.0' ]
|
versions: [ '>=10.0.0' ]
|
||||||
- dependency-name: 'eslint'
|
- dependency-name: 'eslint'
|
||||||
|
|||||||
8
.github/workflows/master.yml
vendored
8
.github/workflows/master.yml
vendored
@ -44,9 +44,17 @@ jobs:
|
|||||||
- name: Generate sitemap
|
- name: Generate sitemap
|
||||||
run: npx grunt exec:sitemap
|
run: npx grunt exec:sitemap
|
||||||
|
|
||||||
|
- name: Setup Chrome
|
||||||
|
id: setup-chrome
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
npx @puppeteer/browsers install chrome@148
|
||||||
|
echo chromedir=$(dirname $(find `pwd`/chrome/* -name chrome -print -quit)) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: UI Tests
|
- name: UI Tests
|
||||||
if: success()
|
if: success()
|
||||||
run: |
|
run: |
|
||||||
|
export PATH=${{ steps.setup-chrome.outputs.chromedir }}:$PATH
|
||||||
sudo apt-get install xvfb
|
sudo apt-get install xvfb
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|
||||||
|
|||||||
10
.github/workflows/pull_requests.yml
vendored
10
.github/workflows/pull_requests.yml
vendored
@ -45,9 +45,17 @@ jobs:
|
|||||||
path: build/prod/*.zip
|
path: build/prod/*.zip
|
||||||
retention-days: 5
|
retention-days: 5
|
||||||
|
|
||||||
|
- name: Setup Chrome
|
||||||
|
id: setup-chrome
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
npx @puppeteer/browsers install chrome@148
|
||||||
|
echo chromedir=$(dirname $(find `pwd`/chrome/* -name chrome -print -quit)) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: UI Tests
|
- name: UI Tests
|
||||||
if: success()
|
if: success()
|
||||||
run: |
|
run: |
|
||||||
|
export PATH=${{ steps.setup-chrome.outputs.chromedir }}:$PATH
|
||||||
sudo apt-get install xvfb
|
sudo apt-get install xvfb
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|
||||||
@ -61,6 +69,6 @@ jobs:
|
|||||||
- name: Production Image Build
|
- name: Production Image Build
|
||||||
if: success()
|
if: success()
|
||||||
id: build-image
|
id: build-image
|
||||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||||
with:
|
with:
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
|||||||
13
.github/workflows/releases.yml
vendored
13
.github/workflows/releases.yml
vendored
@ -46,8 +46,17 @@ jobs:
|
|||||||
- name: Production Build
|
- name: Production Build
|
||||||
run: npx grunt prod
|
run: npx grunt prod
|
||||||
|
|
||||||
- name: UI Tests
|
- name: Setup Chrome
|
||||||
|
id: setup-chrome
|
||||||
|
if: success()
|
||||||
run: |
|
run: |
|
||||||
|
npx @puppeteer/browsers install chrome@148
|
||||||
|
echo chromedir=$(dirname $(find `pwd`/chrome/* -name chrome -print -quit)) >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: UI Tests
|
||||||
|
if: success()
|
||||||
|
run: |
|
||||||
|
export PATH=${{ steps.setup-chrome.outputs.chromedir }}:$PATH
|
||||||
sudo apt-get install xvfb
|
sudo apt-get install xvfb
|
||||||
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
|
||||||
|
|
||||||
@ -75,7 +84,7 @@ jobs:
|
|||||||
password: ${{ env.REGISTRY_PASSWORD }}
|
password: ${{ env.REGISTRY_PASSWORD }}
|
||||||
|
|
||||||
- name: Publish to GHCR
|
- name: Publish to GHCR
|
||||||
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@ src/node/index.mjs
|
|||||||
**/*.DS_Store
|
**/*.DS_Store
|
||||||
tests/browser/output/*
|
tests/browser/output/*
|
||||||
.node-version
|
.node-version
|
||||||
|
chrome
|
||||||
|
|||||||
@ -27,7 +27,7 @@ RUN npm run build
|
|||||||
#########################################
|
#########################################
|
||||||
# Package static build files into nginx #
|
# Package static build files into nginx #
|
||||||
#########################################
|
#########################################
|
||||||
FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:808f7846d21a9c94cf53833e8807a00a33fd0b65cc47fb05b79efe366c2d201f AS cyberchef
|
FROM nginxinc/nginx-unprivileged:stable-alpine@sha256:b9f7ba14f1f7bd3d40d7753584048f92c3aef9ccf5fab14efe4451a8d4c04d63 AS cyberchef
|
||||||
|
|
||||||
LABEL maintainer="GCHQ <oss@gchq.gov.uk>"
|
LABEL maintainer="GCHQ <oss@gchq.gov.uk>"
|
||||||
|
|
||||||
|
|||||||
12
Gruntfile.js
12
Gruntfile.js
@ -89,6 +89,8 @@ module.exports = function (grunt) {
|
|||||||
const compileYear = grunt.template.today("UTC:yyyy"),
|
const compileYear = grunt.template.today("UTC:yyyy"),
|
||||||
compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
|
||||||
pkg = grunt.file.readJSON("package.json"),
|
pkg = grunt.file.readJSON("package.json"),
|
||||||
|
version = process.env.GITHUB_SHA || `v${pkg.version}`,
|
||||||
|
downloadZipFilename = `CyberChef_${version}.zip`,
|
||||||
webpackConfig = require("./webpack.config.js"),
|
webpackConfig = require("./webpack.config.js"),
|
||||||
BUILD_CONSTANTS = {
|
BUILD_CONSTANTS = {
|
||||||
COMPILE_YEAR: JSON.stringify(compileYear),
|
COMPILE_YEAR: JSON.stringify(compileYear),
|
||||||
@ -129,7 +131,9 @@ module.exports = function (grunt) {
|
|||||||
chunks: ["main"],
|
chunks: ["main"],
|
||||||
compileYear: compileYear,
|
compileYear: compileYear,
|
||||||
compileTime: compileTime,
|
compileTime: compileTime,
|
||||||
version: pkg.version,
|
version: version,
|
||||||
|
latestReleaseVersion: pkg.version,
|
||||||
|
downloadZipFilename: downloadZipFilename,
|
||||||
minify: {
|
minify: {
|
||||||
removeComments: true,
|
removeComments: true,
|
||||||
collapseWhitespace: true,
|
collapseWhitespace: true,
|
||||||
@ -245,7 +249,7 @@ module.exports = function (grunt) {
|
|||||||
"!build/prod/index.html",
|
"!build/prod/index.html",
|
||||||
"!build/prod/BundleAnalyzerReport.html",
|
"!build/prod/BundleAnalyzerReport.html",
|
||||||
],
|
],
|
||||||
dest: `build/prod/CyberChef_v${pkg.version}.zip`
|
dest: `build/prod/${downloadZipFilename}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
connect: {
|
connect: {
|
||||||
@ -333,12 +337,12 @@ module.exports = function (grunt) {
|
|||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
return chainCommands([
|
return chainCommands([
|
||||||
`shasum -a 256 build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
`shasum -a 256 build/prod/${downloadZipFilename} | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
||||||
`sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
`sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
||||||
]);
|
]);
|
||||||
default:
|
default:
|
||||||
return chainCommands([
|
return chainCommands([
|
||||||
`sha256sum build/prod/CyberChef_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
`sha256sum build/prod/${downloadZipFilename} | awk '{print $1;}' > build/prod/sha256digest.txt`,
|
||||||
`sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
`sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html`
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
808
package-lock.json
generated
808
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@ -49,10 +49,11 @@
|
|||||||
"@codemirror/search": "^6.7.0",
|
"@codemirror/search": "^6.7.0",
|
||||||
"@codemirror/state": "^6.5.4",
|
"@codemirror/state": "^6.5.4",
|
||||||
"@codemirror/view": "^6.43.0",
|
"@codemirror/view": "^6.43.0",
|
||||||
|
"@puppeteer/browsers": "3.0.3",
|
||||||
"autoprefixer": "^10.5.0",
|
"autoprefixer": "^10.5.0",
|
||||||
"babel-loader": "^10.1.1",
|
"babel-loader": "^10.1.1",
|
||||||
"base64-loader": "^1.0.0",
|
"base64-loader": "^1.0.0",
|
||||||
"chromedriver": "^146.0.6",
|
"chromedriver": "^148.0.3",
|
||||||
"cli-progress": "^3.12.0",
|
"cli-progress": "^3.12.0",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"compression-webpack-plugin": "^12.0.0",
|
"compression-webpack-plugin": "^12.0.0",
|
||||||
@ -86,7 +87,7 @@
|
|||||||
"prompt": "^1.3.0",
|
"prompt": "^1.3.0",
|
||||||
"sitemap": "^8.0.3",
|
"sitemap": "^8.0.3",
|
||||||
"terser": "^5.46.2",
|
"terser": "^5.46.2",
|
||||||
"webpack": "^5.106.2",
|
"webpack": "^5.107.1",
|
||||||
"webpack-bundle-analyzer": "^5.3.0",
|
"webpack-bundle-analyzer": "^5.3.0",
|
||||||
"webpack-dev-server": "^5.0.4",
|
"webpack-dev-server": "^5.0.4",
|
||||||
"webpack-node-externals": "^3.0.0",
|
"webpack-node-externals": "^3.0.0",
|
||||||
@ -110,7 +111,7 @@
|
|||||||
"bootstrap-colorpicker": "^3.4.0",
|
"bootstrap-colorpicker": "^3.4.0",
|
||||||
"bootstrap-material-design": "^4.1.3",
|
"bootstrap-material-design": "^4.1.3",
|
||||||
"browserify-zlib": "^0.2.0",
|
"browserify-zlib": "^0.2.0",
|
||||||
"bson": "^4.7.2",
|
"bson": "^7.2.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"cbor": "9.0.2",
|
"cbor": "9.0.2",
|
||||||
"chi-squared": "^1.1.0",
|
"chi-squared": "^1.1.0",
|
||||||
@ -168,7 +169,7 @@
|
|||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"popper.js": "^1.16.1",
|
"popper.js": "^1.16.1",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"protobufjs": "^7.5.8",
|
"protobufjs": "^7.6.0",
|
||||||
"punycode.js": "^2.3.1",
|
"punycode.js": "^2.3.1",
|
||||||
"qr-image": "^3.2.0",
|
"qr-image": "^3.2.0",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
@ -177,7 +178,7 @@
|
|||||||
"snackbarjs": "^1.1.0",
|
"snackbarjs": "^1.1.0",
|
||||||
"sortablejs": "^1.15.7",
|
"sortablejs": "^1.15.7",
|
||||||
"split.js": "^1.6.5",
|
"split.js": "^1.6.5",
|
||||||
"sql-formatter": "^15.7.4",
|
"sql-formatter": "^15.8.0",
|
||||||
"ssdeep.js": "0.0.3",
|
"ssdeep.js": "0.0.3",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"tesseract.js": "^6.0.1",
|
"tesseract.js": "^6.0.1",
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import bson from "bson";
|
import { deserialize } from "bson";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,7 +37,7 @@ class BSONDeserialise extends Operation {
|
|||||||
if (!input.byteLength) return "";
|
if (!input.byteLength) return "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = bson.deserialize(new Buffer(input));
|
const data = deserialize(new Uint8Array(input));
|
||||||
return JSON.stringify(data, null, 2);
|
return JSON.stringify(data, null, 2);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(err.toString());
|
throw new OperationError(err.toString());
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import bson from "bson";
|
import { serialize } from "bson";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,7 +38,8 @@ class BSONSerialise extends Operation {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(input);
|
const data = JSON.parse(input);
|
||||||
return bson.serialize(data).buffer;
|
const result = serialize(data);
|
||||||
|
return result.buffer.slice(result.byteOffset, result.byteOffset + result.byteLength);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(err.toString());
|
throw new OperationError(err.toString());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -92,7 +92,7 @@ class ParseEthernetFrame extends Operation {
|
|||||||
const packetData = input.slice(offset);
|
const packetData = input.slice(offset);
|
||||||
|
|
||||||
if (outputFormat === "Packet data") {
|
if (outputFormat === "Packet data") {
|
||||||
return Utils.byteArrayToChars(packetData);
|
return Utils.escapeHtml(Utils.byteArrayToChars(packetData));
|
||||||
} else if (outputFormat === "Packet data (hex)") {
|
} else if (outputFormat === "Packet data (hex)") {
|
||||||
return toHex(packetData);
|
return toHex(packetData);
|
||||||
} else if (outputFormat === "Text output") {
|
} else if (outputFormat === "Text output") {
|
||||||
|
|||||||
@ -138,7 +138,7 @@ class ParseIPv4Header extends Operation {
|
|||||||
} else if (outputFormat === "Data (hex)") {
|
} else if (outputFormat === "Data (hex)") {
|
||||||
return toHex(data);
|
return toHex(data);
|
||||||
} else if (outputFormat === "Data (raw)") {
|
} else if (outputFormat === "Data (raw)") {
|
||||||
return Utils.byteArrayToChars(data);
|
return Utils.escapeHtml(Utils.byteArrayToChars(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import BSON from "bson";
|
import { ObjectId } from "bson";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse ObjectID timestamp operation
|
* Parse ObjectID timestamp operation
|
||||||
@ -35,7 +35,7 @@ class ParseObjectIDTimestamp extends Operation {
|
|||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
try {
|
try {
|
||||||
const objectId = new BSON.ObjectID(input);
|
const objectId = new ObjectId(input);
|
||||||
return objectId.getTimestamp().toISOString();
|
return objectId.getTimestamp().toISOString();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(err);
|
throw new OperationError(err);
|
||||||
|
|||||||
@ -15,6 +15,20 @@ import Utils from "../Utils.mjs";
|
|||||||
const d3 = d3temp.default ? d3temp.default : d3temp;
|
const d3 = d3temp.default ? d3temp.default : d3temp;
|
||||||
const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp;
|
const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes D3's internal bound data from a nodom tree before serialization.
|
||||||
|
* nodom serializes enumerable expando properties such as __data__ as attributes,
|
||||||
|
* so leaving them on attacker-controlled values can create executable markup.
|
||||||
|
*
|
||||||
|
* @param {Object} node
|
||||||
|
*/
|
||||||
|
function clearD3BoundData(node) {
|
||||||
|
delete node.__data__;
|
||||||
|
|
||||||
|
if (!node.childNodes) return;
|
||||||
|
node.childNodes.forEach(clearD3BoundData);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Series chart operation
|
* Series chart operation
|
||||||
*/
|
*/
|
||||||
@ -222,6 +236,8 @@ class SeriesChart extends Operation {
|
|||||||
.text(serie.name);
|
.text(serie.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
clearD3BoundData(svg.node());
|
||||||
|
|
||||||
return svg._groups[0][0].outerHTML;
|
return svg._groups[0][0].outerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,14 @@ class App {
|
|||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
this.ingId = 0;
|
this.ingId = 0;
|
||||||
|
|
||||||
|
// stateChangeId increments on every statechange dispatch; bakeStateId records
|
||||||
|
// the stateChangeId captured when the most recent bake started. autoBake uses
|
||||||
|
// these to decide whether the output is genuinely stale, so a debounced
|
||||||
|
// autoBake firing shortly after a manual bake doesn't clobber the bake's
|
||||||
|
// hideStaleIndicator with a redundant showStaleIndicator.
|
||||||
|
this.stateChangeId = 0;
|
||||||
|
this.bakeStateId = -1;
|
||||||
|
|
||||||
this.appLoaded = false;
|
this.appLoaded = false;
|
||||||
this.workerLoaded = false;
|
this.workerLoaded = false;
|
||||||
this.waitersLoaded = false;
|
this.waitersLoaded = false;
|
||||||
@ -136,6 +144,9 @@ class App {
|
|||||||
bake(step=false) {
|
bake(step=false) {
|
||||||
if (this.baking) return;
|
if (this.baking) return;
|
||||||
|
|
||||||
|
// Record which state version this bake is covering.
|
||||||
|
this.bakeStateId = this.stateChangeId;
|
||||||
|
|
||||||
// Reset attemptHighlight flag
|
// Reset attemptHighlight flag
|
||||||
this.options.attemptHighlight = true;
|
this.options.attemptHighlight = true;
|
||||||
|
|
||||||
@ -166,7 +177,10 @@ class App {
|
|||||||
nums: [this.manager.tabs.getActiveTab("input")],
|
nums: [this.manager.tabs.getActiveTab("input")],
|
||||||
step: false
|
step: false
|
||||||
});
|
});
|
||||||
} else {
|
} else if (this.bakeStateId < this.stateChangeId) {
|
||||||
|
// Only show stale-indicator if the most recent bake didn't cover the
|
||||||
|
// current state. Without this guard, a debounced autoBake firing after
|
||||||
|
// a manual bake completed would re-show the indicator on fresh output.
|
||||||
this.manager.controls.showStaleIndicator();
|
this.manager.controls.showStaleIndicator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -768,6 +782,10 @@ class App {
|
|||||||
* @param {event} e
|
* @param {event} e
|
||||||
*/
|
*/
|
||||||
stateChange(e) {
|
stateChange(e) {
|
||||||
|
// Bump the state-change counter synchronously so a manual bake invoked between
|
||||||
|
// here and the debounced autoBake firing can record it via bakeStateId.
|
||||||
|
this.stateChangeId++;
|
||||||
|
|
||||||
debounce(function() {
|
debounce(function() {
|
||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
this.autoBake();
|
this.autoBake();
|
||||||
|
|||||||
@ -868,15 +868,15 @@
|
|||||||
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.
|
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.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h6>CyberChef v<%= htmlWebpackPlugin.options.version %></h6>
|
<h6>CyberChef <%= htmlWebpackPlugin.options.version %></h6>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Build time: <%= htmlWebpackPlugin.options.compileTime %></li>
|
<li>Build time: <%= htmlWebpackPlugin.options.compileTime %></li>
|
||||||
<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>
|
<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>
|
||||||
<li>© Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %></li>
|
<li>© Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %></li>
|
||||||
<li>Released under the Apache Licence, Version 2.0</li>
|
<li>Released under the Apache Licence, Version 2.0</li>
|
||||||
<li>SHA256 hash: DOWNLOAD_HASH_PLACEHOLDER</li>
|
<li>SHA256 hash: DOWNLOAD_HASH_PLACEHOLDER</li>
|
||||||
</ul>
|
</ul>
|
||||||
<a href="CyberChef_v<%= htmlWebpackPlugin.options.version %>.zip" download class="btn btn-outline-primary">Download ZIP file</a>
|
<a href="<%= htmlWebpackPlugin.options.downloadZipFilename %>" download class="btn btn-outline-primary">Download ZIP file</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button>
|
<button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button>
|
||||||
|
|||||||
@ -51,14 +51,17 @@ function setInput(browser, input, type=true) {
|
|||||||
*/
|
*/
|
||||||
function bake(browser) {
|
function bake(browser) {
|
||||||
browser
|
browser
|
||||||
|
// Let any pending debounced inputChange/stateChange (~20ms each) fire so the
|
||||||
|
// worker has the latest input buffer before we ask it to bake.
|
||||||
|
.pause(50)
|
||||||
// Ensure we're not currently busy
|
// Ensure we're not currently busy
|
||||||
.waitForElementNotVisible("#output-loader", 5000)
|
.waitForElementNotVisible("#output-loader", 10000)
|
||||||
.expect.element("#bake span").text.to.equal("BAKE!");
|
.expect.element("#bake span").text.to.equal("BAKE!");
|
||||||
|
|
||||||
browser
|
browser
|
||||||
.click("#bake")
|
.click("#bake")
|
||||||
.waitForElementNotVisible("#stale-indicator", 5000)
|
.waitForElementNotVisible("#stale-indicator", 10000)
|
||||||
.waitForElementNotVisible("#output-loader", 5000);
|
.waitForElementNotVisible("#output-loader", 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @function
|
/** @function
|
||||||
|
|||||||
@ -126,6 +126,7 @@ import "./tests/NormaliseUnicode.mjs";
|
|||||||
import "./tests/NTLM.mjs";
|
import "./tests/NTLM.mjs";
|
||||||
import "./tests/OTP.mjs";
|
import "./tests/OTP.mjs";
|
||||||
import "./tests/ParseEthernetFrame.mjs";
|
import "./tests/ParseEthernetFrame.mjs";
|
||||||
|
import "./tests/ParseIPv4Header.mjs";
|
||||||
import "./tests/ParseIPRange.mjs";
|
import "./tests/ParseIPRange.mjs";
|
||||||
import "./tests/ParseObjectIDTimestamp.mjs";
|
import "./tests/ParseObjectIDTimestamp.mjs";
|
||||||
import "./tests/ParseQRCode.mjs";
|
import "./tests/ParseQRCode.mjs";
|
||||||
|
|||||||
@ -41,6 +41,17 @@ TestRegister.addTests([
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Series chart escapes x-axis values in serialized SVG",
|
||||||
|
input: `s,x"><script>globalThis.seriesChartInjected=1</script><g a=",1`,
|
||||||
|
unexpectedMatch: /<script>|__data__=/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Series chart",
|
||||||
|
"args": ["Line feed", "Comma", "", 1, "red"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Heatmap chart",
|
name: "Heatmap chart",
|
||||||
input: "100 100\n200 200\n300 300\n400 400\n500 500",
|
input: "100 100\n200 200\n300 300\n400 400\n500 500",
|
||||||
|
|||||||
@ -41,5 +41,16 @@ TestRegister.addTests([
|
|||||||
"args": ["Hex", "Text output"]
|
"args": ["Hex", "Text output"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parse Ethernet frame escapes packet data HTML",
|
||||||
|
input: "000000000000ffffffffffff08003c696d67207372633d78206f6e6572726f723d616c6572742831293e3c7363726970743e616c6572742832293c2f7363726970743e",
|
||||||
|
expectedOutput: "<img src=x onerror=alert(1)><script>alert(2)</script>",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "Parse Ethernet frame",
|
||||||
|
"args": ["Hex", "Packet data"]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|||||||
23
tests/operations/tests/ParseIPv4Header.mjs
Normal file
23
tests/operations/tests/ParseIPv4Header.mjs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Parse IPv4 header tests.
|
||||||
|
*
|
||||||
|
* @author C85297 [95289555+C85297@users.noreply.github.com]
|
||||||
|
* @copyright Crown Copyright 2026
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Parse IPv4 header: Correctly formatted HTML output",
|
||||||
|
input: "45 00 00 3c 1c 46 40 00 40 06 b1 e6 c0 a8 00 01 c0 a8 00 02 3c 73 63 72 69 70 74 3e 61 6c 65 72 74 28 31 33 33 37 29 3c 2f 73 63 72 69 70 74 3e",
|
||||||
|
expectedOutput: "<script>alert(1337)</script>",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Parse IPv4 header",
|
||||||
|
args: ["Hex", "Data (raw)"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
Loading…
x
Reference in New Issue
Block a user