From 2b99b96198be363b023fadc55e9a075e6a55cac0 Mon Sep 17 00:00:00 2001
From: C85297 <95289555+C85297@users.noreply.github.com>
Date: Mon, 27 Apr 2026 15:48:13 +0100
Subject: [PATCH 1/2] Fix #584: URL encode takes binary input
---
src/core/operations/URLEncode.mjs | 40 ++++++++++++----------
tests/operations/tests/URLEncodeDecode.mjs | 26 ++++++++++++++
2 files changed, 48 insertions(+), 18 deletions(-)
diff --git a/src/core/operations/URLEncode.mjs b/src/core/operations/URLEncode.mjs
index a5efd2135c..9ea9f365d1 100644
--- a/src/core/operations/URLEncode.mjs
+++ b/src/core/operations/URLEncode.mjs
@@ -21,7 +21,7 @@ class URLEncode extends Operation {
this.module = "URL";
this.description = "Encodes problematic characters into percent-encoding, a format supported by URIs/URLs.
e.g. = becomes %3d";
this.infoURL = "https://wikipedia.org/wiki/Percent-encoding";
- this.inputType = "string";
+ this.inputType = "byteArray";
this.outputType = "string";
this.args = [
{
@@ -33,34 +33,38 @@ class URLEncode extends Operation {
}
/**
- * @param {string} input
+ * @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const encodeAll = args[0];
- return encodeAll ? this.encodeAllChars(input) : encodeURI(input);
+ return this.encodeBytes(input, encodeAll);
}
/**
- * Encode characters in URL outside of encodeURI() function spec
+ * Encode bytes in URL using percent encoding.
*
- * @param {string} str
+ * @param {byteArray} bytes
+ * @param {boolean} encodeAll
* @returns {string}
*/
- encodeAllChars (str) {
- // TODO Do this programmatically
- return encodeURIComponent(str)
- .replace(/!/g, "%21")
- .replace(/#/g, "%23")
- .replace(/'/g, "%27")
- .replace(/\(/g, "%28")
- .replace(/\)/g, "%29")
- .replace(/\*/g, "%2A")
- .replace(/-/g, "%2D")
- .replace(/\./g, "%2E")
- .replace(/_/g, "%5F")
- .replace(/~/g, "%7E");
+ encodeBytes(bytes, encodeAll) {
+ const safeChars = encodeAll ?
+ /^[A-Za-z0-9]$/ :
+ /^[A-Za-z0-9:/?#\[\]@!$&'\(\)*+,;=%]$/;
+
+ let output = "";
+
+ for (const byte of bytes) {
+ const char = String.fromCharCode(byte);
+
+ output += safeChars.test(char) ?
+ char :
+ "%" + byte.toString(16).toUpperCase().padStart(2, "0");
+ }
+
+ return output;
}
}
diff --git a/tests/operations/tests/URLEncodeDecode.mjs b/tests/operations/tests/URLEncodeDecode.mjs
index 444f76d37a..8d9d09db58 100644
--- a/tests/operations/tests/URLEncodeDecode.mjs
+++ b/tests/operations/tests/URLEncodeDecode.mjs
@@ -89,4 +89,30 @@ TestRegister.addTests([
},
],
},
+ {
+ name: "URLEncode: encodes UTF-8 text as UTF-8 bytes",
+ input: "你好",
+ expectedOutput: "%E4%BD%A0%E5%A5%BD",
+ recipeConfig: [
+ {
+ op: "URL Encode",
+ args: [false],
+ },
+ ],
+ },
+ {
+ name: "URLEncode: preserves raw bytes from From Hex",
+ input: "6c6567697466696c6580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090746869737761737375706f736564746f6265616e6578706c6f6974",
+ expectedOutput: "legitfile%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%90thiswassuposedtobeanexploit",
+ recipeConfig: [
+ {
+ op: "From Hex",
+ args: ["None"],
+ },
+ {
+ op: "URL Encode",
+ args: [false],
+ },
+ ],
+ },
]);
From e949087c539a7a71761f01992528e8b0f2e29bfd Mon Sep 17 00:00:00 2001
From: C85297 <95289555+C85297@users.noreply.github.com>
Date: Mon, 27 Apr 2026 16:33:47 +0100
Subject: [PATCH 2/2] Fix lint
---
src/core/operations/URLEncode.mjs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/operations/URLEncode.mjs b/src/core/operations/URLEncode.mjs
index 9ea9f365d1..99eec91d7a 100644
--- a/src/core/operations/URLEncode.mjs
+++ b/src/core/operations/URLEncode.mjs
@@ -52,7 +52,7 @@ class URLEncode extends Operation {
encodeBytes(bytes, encodeAll) {
const safeChars = encodeAll ?
/^[A-Za-z0-9]$/ :
- /^[A-Za-z0-9:/?#\[\]@!$&'\(\)*+,;=%]$/;
+ /^[A-Za-z0-9:/?#[\]@!$&'()*+,;=%]$/;
let output = "";