feat: add 'Last only' defang mode to Defang IP Addresses

Adds an opt-in "Last only" boolean argument (default false to preserve
existing behaviour) to the Defang IP Addresses operation. When enabled,
only the final separator of each matched IP is replaced:

- IPv4: 1.2.3.4 -> 1.2.3[.]4 (instead of 1[.]2[.]3[.]4)
- IPv6: 2001:0db8::1 -> 2001:0db8::[:]1

This matches the common SOC-tool default (e.g. Splunk) where the
defanged form stays visually close to the original while still
rendering the address invalid.
This commit is contained in:
HarelKatz 2026-05-15 18:06:21 +03:00
parent 0bb5472e50
commit 50a7613bfd
2 changed files with 72 additions and 4 deletions

View File

@ -20,11 +20,17 @@ class DefangIPAddresses extends Operation {
this.name = "Defang IP Addresses"; this.name = "Defang IP Addresses";
this.module = "Default"; this.module = "Default";
this.description = "Takes a IPv4 or IPv6 address and 'Defangs' it, meaning the IP becomes invalid, removing the risk of accidentally utilising it as an IP address."; this.description = "Takes a IPv4 or IPv6 address and 'Defangs' it, meaning the IP becomes invalid, removing the risk of accidentally utilising it as an IP address.<br><br>When 'Last only' is enabled, only the final separator of each IP is replaced (e.g. <code>1.2.3.4</code> becomes <code>1.2.3[.]4</code>), keeping the address visually closer to its original form while still rendering it invalid.";
this.infoURL = "https://isc.sans.edu/forums/diary/Defang+all+the+things/22744/"; this.infoURL = "https://isc.sans.edu/forums/diary/Defang+all+the+things/22744/";
this.inputType = "string"; this.inputType = "string";
this.outputType = "string"; this.outputType = "string";
this.args = []; this.args = [
{
name: "Last only",
type: "boolean",
value: false
}
];
this.checks = [ this.checks = [
{ {
pattern: "^\\s*(([0-9]{1,3}\\.){3}[0-9]{1,3}|([0-9a-f]{4}:){7}[0-9a-f]{4})\\s*$", pattern: "^\\s*(([0-9]{1,3}\\.){3}[0-9]{1,3}|([0-9a-f]{4}:){7}[0-9a-f]{4})\\s*$",
@ -44,12 +50,14 @@ class DefangIPAddresses extends Operation {
* @returns {string} * @returns {string}
*/ */
run(input, args) { run(input, args) {
const [lastOnly] = args;
input = input.replace(IPV4_REGEX, x => { input = input.replace(IPV4_REGEX, x => {
return x.replace(/\./g, "[.]"); return defangSeparators(x, ".", "[.]", lastOnly);
}); });
input = input.replace(IPV6_REGEX, x => { input = input.replace(IPV6_REGEX, x => {
return x.replace(/:/g, "[:]"); return defangSeparators(x, ":", "[:]", lastOnly);
}); });
return input; return input;
@ -59,6 +67,26 @@ class DefangIPAddresses extends Operation {
export default DefangIPAddresses; export default DefangIPAddresses;
/**
* Replaces a separator character with a defanged token.
* If lastOnly is true, only the final occurrence is replaced.
*
* @param {string} match
* @param {string} sep
* @param {string} token
* @param {boolean} lastOnly
* @returns {string}
*/
function defangSeparators(match, sep, token, lastOnly) {
if (!lastOnly) {
return match.split(sep).join(token);
}
const idx = match.lastIndexOf(sep);
if (idx === -1) return match;
return match.slice(0, idx) + token + match.slice(idx + sep.length);
}
/** /**
* IPV4 regular expression * IPV4 regular expression
*/ */

View File

@ -39,5 +39,45 @@ TestRegister.addTests([
args: [], args: [],
}, },
], ],
}, {
name: "Defang IP: Last only — IPV4",
input: "192.168.1.1",
expectedOutput: "192.168.1[.]1",
recipeConfig: [
{
op: "Defang IP Addresses",
args: [true],
},
],
}, {
name: "Defang IP: Last only — IPV6",
input: "2001:0db8:85a3:0000:0000:8a2e:0370:7343",
expectedOutput: "2001:0db8:85a3:0000:0000:8a2e:0370[:]7343",
recipeConfig: [
{
op: "Defang IP Addresses",
args: [true],
},
],
}, {
name: "Defang IP: Last only — IPV6 shorthand",
input: "2001:db8:3c4d:15::1a2f:1a2b",
expectedOutput: "2001:db8:3c4d:15::1a2f[:]1a2b",
recipeConfig: [
{
op: "Defang IP Addresses",
args: [true],
},
],
}, {
name: "Defang IP: Last only — multiple IPs in text",
input: "From 10.0.0.1 to 192.168.1.254",
expectedOutput: "From 10.0.0[.]1 to 192.168.1[.]254",
recipeConfig: [
{
op: "Defang IP Addresses",
args: [true],
},
],
}, },
]); ]);