From 44e06ab4d79011b35fc7b8607455be4478cd599f Mon Sep 17 00:00:00 2001
From: HarelKatz <34490550+HarelKatz@users.noreply.github.com>
Date: Fri, 15 May 2026 19:52:59 +0300
Subject: [PATCH 1/7] refactor: thread defang-aware separators through Extract
IP addresses
Adds an "Include defanged" boolean arg (default false) and refactors
the IPv4/IPv6/removeLocal regex assembly to use dotSep/colonSep
variables. With the arg off the variables collapse to the original
literal separators, so the regex string is byte-identical to the
pre-change op. Behaviour unchanged; no new tests yet.
---
src/core/operations/ExtractIPAddresses.mjs | 33 ++++++++++++++++------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/src/core/operations/ExtractIPAddresses.mjs b/src/core/operations/ExtractIPAddresses.mjs
index b74ec8fe..6aa2c438 100644
--- a/src/core/operations/ExtractIPAddresses.mjs
+++ b/src/core/operations/ExtractIPAddresses.mjs
@@ -54,6 +54,11 @@ class ExtractIPAddresses extends Operation {
name: "Unique",
type: "boolean",
value: false
+ },
+ {
+ name: "Include defanged",
+ type: "boolean",
+ value: false
}
];
}
@@ -64,7 +69,13 @@ class ExtractIPAddresses extends Operation {
* @returns {string}
*/
run(input, args) {
- const [includeIpv4, includeIpv6, removeLocal, displayTotal, sort, unique] = args,
+ const [includeIpv4, includeIpv6, removeLocal, displayTotal, sort, unique, includeDefanged] = args,
+
+ // Defang-aware separator patterns. When includeDefanged is false these
+ // collapse to the original literal separators, so the regex behaviour
+ // is byte-for-byte identical to the pre-change op.
+ dotSep = includeDefanged ? "(?:\\.|\\[\\.\\])" : "\\.",
+ colonSep = includeDefanged ? "(?::|\\[:\\])" : ":",
// IPv4 decimal groups can have values 0 to 255. To construct a regex the following sub-regex is reused:
ipv4DecimalByte = "(?:25[0-5]|2[0-4]\\d|1?[0-9]\\d|\\d)",
@@ -74,13 +85,16 @@ class ExtractIPAddresses extends Operation {
lookBehind = "(?
Date: Fri, 15 May 2026 19:53:46 +0300
Subject: [PATCH 2/7] test: assert Extract IP defang-off ignores defanged input
---
tests/operations/tests/ExtractIPAddresses.mjs | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/tests/operations/tests/ExtractIPAddresses.mjs b/tests/operations/tests/ExtractIPAddresses.mjs
index 13922e64..b758ba5d 100644
--- a/tests/operations/tests/ExtractIPAddresses.mjs
+++ b/tests/operations/tests/ExtractIPAddresses.mjs
@@ -129,5 +129,16 @@ TestRegister.addTests([
},
],
},
+ {
+ name: "ExtractIPAddress backwards-compat: defang off ignores [.] defanged input",
+ input: "192[.]168[.]1[.]1 plain 10.0.0.1",
+ expectedOutput: "10.0.0.1",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, false]
+ },
+ ],
+ },
]);
From 340d081c011d3d20063f23200547a1df24efad87 Mon Sep 17 00:00:00 2001
From: HarelKatz <34490550+HarelKatz@users.noreply.github.com>
Date: Fri, 15 May 2026 19:54:36 +0300
Subject: [PATCH 3/7] test: extract fully-defanged IPv4 and IPv6
---
tests/operations/tests/ExtractIPAddresses.mjs | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/tests/operations/tests/ExtractIPAddresses.mjs b/tests/operations/tests/ExtractIPAddresses.mjs
index b758ba5d..fd0b0f47 100644
--- a/tests/operations/tests/ExtractIPAddresses.mjs
+++ b/tests/operations/tests/ExtractIPAddresses.mjs
@@ -140,5 +140,38 @@ TestRegister.addTests([
},
],
},
+ {
+ name: "ExtractIPAddress defang on: fully defanged IPv4",
+ input: "192[.]168[.]1[.]1",
+ expectedOutput: "192[.]168[.]1[.]1",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: fully defanged IPv6 long form",
+ input: "2001[:]0db8[:]85a3[:]0000[:]0000[:]8a2e[:]0370[:]7343",
+ expectedOutput: "2001[:]0db8[:]85a3[:]0000[:]0000[:]8a2e[:]0370[:]7343",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [false, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: fully defanged IPv6 shorthand",
+ input: "2001[:]db8[:][:]1",
+ expectedOutput: "2001[:]db8[:][:]1",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [false, true, false, false, false, false, true]
+ },
+ ],
+ },
]);
From 695103728fda75b02bfa7240aba69e3edb7f1eab Mon Sep 17 00:00:00 2001
From: HarelKatz <34490550+HarelKatz@users.noreply.github.com>
Date: Fri, 15 May 2026 19:57:36 +0300
Subject: [PATCH 4/7] test: extract partial-defang IPv4 (decimal + octal) and
mixed inputs
---
tests/operations/tests/ExtractIPAddresses.mjs | 44 +++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/tests/operations/tests/ExtractIPAddresses.mjs b/tests/operations/tests/ExtractIPAddresses.mjs
index fd0b0f47..4d40f976 100644
--- a/tests/operations/tests/ExtractIPAddresses.mjs
+++ b/tests/operations/tests/ExtractIPAddresses.mjs
@@ -173,5 +173,49 @@ TestRegister.addTests([
},
],
},
+ {
+ name: "ExtractIPAddress defang on: partial defang IPv4",
+ input: "192.168[.]1.1 and 1[.]2.3[.]4",
+ expectedOutput: "192.168[.]1.1\n1[.]2.3[.]4",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: mixed plain and defanged in one input",
+ input: "plain 10.0.0.1 defanged 8[.]8[.]8[.]8",
+ expectedOutput: "10.0.0.1\n8[.]8[.]8[.]8",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: defanged octal IPv4",
+ input: "0123[.]0177[.]0234[.]0377",
+ expectedOutput: "0123[.]0177[.]0234[.]0377",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: partial-defang octal IPv4",
+ input: "0123.0177[.]0234[.]0377",
+ expectedOutput: "0123.0177[.]0234[.]0377",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, true]
+ },
+ ],
+ },
]);
From 31545dd0de2f3dc9c51e13fe6ba3ee402654a617 Mon Sep 17 00:00:00 2001
From: HarelKatz <34490550+HarelKatz@users.noreply.github.com>
Date: Fri, 15 May 2026 19:58:28 +0300
Subject: [PATCH 5/7] test: removeLocal filters full and partial defanged local
IPs
---
tests/operations/tests/ExtractIPAddresses.mjs | 33 +++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/tests/operations/tests/ExtractIPAddresses.mjs b/tests/operations/tests/ExtractIPAddresses.mjs
index 4d40f976..801e34f6 100644
--- a/tests/operations/tests/ExtractIPAddresses.mjs
+++ b/tests/operations/tests/ExtractIPAddresses.mjs
@@ -217,5 +217,38 @@ TestRegister.addTests([
},
],
},
+ {
+ name: "ExtractIPAddress defang on + removeLocal: full-defang local 10/8 filtered",
+ input: "10[.]0[.]0[.]1 public 8[.]8[.]8[.]8",
+ expectedOutput: "8[.]8[.]8[.]8",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, true, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on + removeLocal: partial-defang local 192.168 filtered",
+ input: "192.168[.]1[.]100 keeps 1.1.1.1",
+ expectedOutput: "1.1.1.1",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, true, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on + removeLocal: full-defang 172.16/12 filtered",
+ input: "172[.]16[.]0[.]1 public 9[.]9[.]9[.]9",
+ expectedOutput: "9[.]9[.]9[.]9",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, true, false, false, false, true]
+ },
+ ],
+ },
]);
From 8c2429736c8684110a1d3341aa8852f9c654cbb8 Mon Sep 17 00:00:00 2001
From: HarelKatz <34490550+HarelKatz@users.noreply.github.com>
Date: Fri, 15 May 2026 19:59:24 +0300
Subject: [PATCH 6/7] test: unique/sort/URI-literal/edge-case behaviour with
Extract IP defang
---
tests/operations/tests/ExtractIPAddresses.mjs | 99 +++++++++++++++++++
1 file changed, 99 insertions(+)
diff --git a/tests/operations/tests/ExtractIPAddresses.mjs b/tests/operations/tests/ExtractIPAddresses.mjs
index 801e34f6..ab8f9d48 100644
--- a/tests/operations/tests/ExtractIPAddresses.mjs
+++ b/tests/operations/tests/ExtractIPAddresses.mjs
@@ -250,5 +250,104 @@ TestRegister.addTests([
},
],
},
+ {
+ name: "ExtractIPAddress defang on + unique: plain and defanged kept distinct",
+ input: "1.1.1.1 1[.]1[.]1[.]1 1.1.1.1",
+ expectedOutput: "1.1.1.1\n1[.]1[.]1[.]1",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, true, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on + sort: plain group sorts numerically before defanged group sorts lexically",
+ input: "200.1.1.1 5.5.5.5 100[.]100[.]100[.]100 10[.]0[.]0[.]1",
+ expectedOutput: "5.5.5.5\n200.1.1.1\n10[.]0[.]0[.]1\n100[.]100[.]100[.]100",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, true, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: IPv6 URI literal brackets stripped, inner extracted",
+ input: "Connect to [2001:db8::1]:8080 please",
+ expectedOutput: "2001:db8::1",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [false, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: empty input",
+ input: "",
+ expectedOutput: "",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: trailing-digit trap does not over-extend defanged IP",
+ input: "abc 192[.]168[.]1[.]1234",
+ expectedOutput: "",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on + displayTotal: count line includes defanged matches",
+ input: "1.1.1.1 2[.]2[.]2[.]2 3[.]3[.]3[.]3",
+ expectedOutput: "Total found: 3\n\n1.1.1.1\n2[.]2[.]2[.]2\n3[.]3[.]3[.]3",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, true, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on, IPv4 toggle off: defanged IPv4 input matches nothing",
+ input: "192[.]168[.]1[.]1",
+ expectedOutput: "",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [false, true, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on, IPv6 toggle off: defanged IPv6 input matches nothing",
+ input: "2001[:]db8[:][:]1",
+ expectedOutput: "",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, false, false, false, false, false, true]
+ },
+ ],
+ },
+ {
+ name: "ExtractIPAddress defang on: pure ASCII text with no IPs returns empty",
+ input: "the quick brown fox jumps over the lazy dog (no addresses here)",
+ expectedOutput: "",
+ recipeConfig: [
+ {
+ "op": "Extract IP addresses",
+ "args": [true, true, false, false, false, false, true]
+ },
+ ],
+ },
]);
From 981371e98d1be8679a1c9abaeef004ee30d4940d Mon Sep 17 00:00:00 2001
From: HarelKatz <34490550+HarelKatz@users.noreply.github.com>
Date: Fri, 15 May 2026 20:04:37 +0300
Subject: [PATCH 7/7] docs: update Extract IP description for Include defanged
arg
---
src/core/operations/ExtractIPAddresses.mjs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/operations/ExtractIPAddresses.mjs b/src/core/operations/ExtractIPAddresses.mjs
index 6aa2c438..f169e340 100644
--- a/src/core/operations/ExtractIPAddresses.mjs
+++ b/src/core/operations/ExtractIPAddresses.mjs
@@ -21,7 +21,7 @@ class ExtractIPAddresses extends Operation {
this.name = "Extract IP addresses";
this.module = "Regex";
- this.description = "Extracts all IPv4 and IPv6 addresses.
Warning: Given a string 1.2.3.4.5.6.7.8, this will match 1.2.3.4 and 5.6.7.8 so always check the original input!";
+ this.description = "Extracts all IPv4 and IPv6 addresses.
When 'Include defanged' is enabled, addresses defanged with [.] (IPv4) or [:] (IPv6) are also extracted, including partial defangs (e.g. 192.168[.]1.1). Matches are returned as-is; chain Fang IP Addresses after if you need clean addresses. With 'Sort' enabled, defanged matches sort lexicographically after the plain-IP group.
Warning: Given a string 1.2.3.4.5.6.7.8, this will match 1.2.3.4 and 5.6.7.8 so always check the original input!";
this.inputType = "string";
this.outputType = "string";
this.args = [