Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21,713 changes: 21,713 additions & 0 deletions src/core/config/OperationConfig.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/core/operations/Argon2.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Argon2 extends Operation {

this.name = "Argon2";
this.module = "Crypto";
this.description = "Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It was designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.<br><br>Enter the password in the input to generate its hash.<br><br><strong>OWASP Recommendation:</strong> Use Argon2id with at least 19 MiB memory, 2 iterations, and parallelism of 1 (default settings).";
this.description = "Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It was designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.<br><br>Enter the password in the input to generate its hash.";
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes OWASP-recommended security guidance that was added in the MCP version. The removed description included important security recommendations about using Argon2id with at least 19 MiB memory, 2 iterations, and parallelism of 1. Removing this guidance may lead users to use insecure parameters without understanding the security implications.

Suggested change
this.description = "Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It was designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.<br><br>Enter the password in the input to generate its hash.";
this.description = "Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It was designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.<br><br>Enter the password in the input to generate its hash.<br><br><strong>Security guidance:</strong> For password hashing, OWASP recommends using <code>Argon2id</code> with at least 19&nbsp;MiB of memory (approximately 19456&nbsp;KiB), 2 iterations, and a parallelism of 1 for interactive logins. These settings correspond to the <em>Type</em> (set to Argon2id), <em>Memory (KiB)</em>, <em>Iterations</em>, and <em>Parallelism</em> options below. Consider increasing the memory/iterations further if your environment allows, and always validate parameters against current OWASP Password Storage Cheat Sheet guidance.";

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The new default parameters for Argon2 are significantly weaker and do not follow modern security recommendations. These changes could lead to users unknowingly generating weak password hashes.

  • The default memory has been reduced from 19MiB to 4MiB. OWASP recommends at least 19MiB for Argon2.
  • The default type has been changed from Argon2id to Argon2i. Argon2id is generally recommended as it protects against both side-channel and timing attacks.
  • The description no longer includes the OWASP recommendation, which previously guided users to secure settings.

It is strongly recommended to revert to more secure defaults (19456 KiB memory, Argon2id as the default type) and restore the OWASP recommendation in the description.

this.infoURL = "https://wikipedia.org/wiki/Argon2";
this.inputType = "string";
this.outputType = "string";
Expand All @@ -36,12 +36,12 @@ class Argon2 extends Operation {
{
"name": "Iterations",
"type": "number",
"value": 2
"value": 3
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change downgrades the default iterations from 2 (OWASP-recommended minimum) to 3, which appears to be an increase but actually conflicts with the simultaneously downgraded memory parameter. The MCP version used 2 iterations with 19,456 KiB memory to meet OWASP recommendations for Argon2id. Changing to 3 iterations but reducing memory to 4,096 KiB results in weaker overall security despite the higher iteration count, as Argon2's security depends heavily on memory cost.

Copilot uses AI. Check for mistakes.
},
{
"name": "Memory (KiB)",
"type": "number",
"value": 19456
"value": 4096
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change significantly downgrades the default memory parameter from 19,456 KiB (19 MiB, OWASP-recommended minimum) to 4,096 KiB (4 MiB). This reduction to less than 1/4 of the recommended value substantially weakens Argon2's resistance to brute-force and GPU-based attacks. Argon2's primary defense mechanism is memory hardness, and reducing the memory cost makes it much easier for attackers to parallelize cracking attempts.

Suggested change
"value": 4096
"value": 19456

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The default parameters for Argon2 have been weakened. The memory requirement was reduced from 19,456 KiB to 4,096 KiB, and the default type was changed from Argon2id to Argon2i. OWASP recommends Argon2id with at least 19 MiB of memory to provide adequate resistance against GPU-based attacks.

Suggested change
"value": 4096
"value": 19456

},
{
"name": "Parallelism",
Expand All @@ -56,7 +56,7 @@ class Argon2 extends Operation {
{
"name": "Type",
"type": "option",
"value": ["Argon2id", "Argon2i", "Argon2d"],
"value": ["Argon2i", "Argon2d", "Argon2id"],
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change reorders the Argon2 type options, moving Argon2id from the first position (default) to the last. The MCP version intentionally set Argon2id as the default (index 0) because it provides the best balance of security against both side-channel and GPU attacks, as recommended by OWASP. Changing the default to Argon2i weakens security for users who don't explicitly select the type, as Argon2i is more vulnerable to GPU-based attacks.

Suggested change
"value": ["Argon2i", "Argon2d", "Argon2id"],
"value": ["Argon2id", "Argon2i", "Argon2d"],

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Changing the default Argon2 type to Argon2i reduces resistance to side-channel attacks compared to Argon2id, which is the current recommended default for password hashing.

Suggested change
"value": ["Argon2i", "Argon2d", "Argon2id"],
"value": ["Argon2id", "Argon2i", "Argon2d"],

"defaultIndex": 0
},
{
Expand Down
40 changes: 11 additions & 29 deletions src/core/operations/DeriveEVPKey.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
{
"name": "Iterations",
"type": "number",
"value": 10000
"value": 1
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change reintroduces CWE-916 (Insufficient Password Hash Iterations) vulnerability. The MCP version increased the default from 1 to 10,000 iterations to meet NIST SP 800-132 recommended minimum for PBKDF2. Reverting to 1 iteration makes derived keys trivially vulnerable to brute-force attacks. While the lgtm comment notes this is for OpenSSL compatibility (not password storage), using only 1 iteration significantly weakens the key derivation and contradicts security best practices documented in the MCP version's security fixes.

Suggested change
"value": 1
"value": 10000

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The default iteration count for EVP key derivation has been reduced to 1, making derived keys trivial to brute-force. This is a critical security vulnerability; NIST SP 800-63B recommends at least 10,000 iterations for password-based key derivation.

Suggested change
"value": 1
"value": 10000

},
{
"name": "Hashing function",
Expand Down Expand Up @@ -68,29 +68,14 @@
iterations = args[2],
hasher = args[3],
salt = CryptoJS.enc.Latin1.parse(
Utils.convertToByteString(args[4].string, args[4].option));

// Enforce minimum iteration count for security (NIST SP 800-63B recommends 10,000+)
const minIterations = 10000;
const actualIterations = Math.max(iterations, minIterations);

let warning = "";
if (iterations < minIterations) {
warning = `Warning: Iteration count ${iterations} is below the minimum secure value of ${minIterations}. Using ${minIterations} iterations instead.\n\n`;
}

// CodeQL suppression: This intentionally implements OpenSSL's EVP_BytesToKey for
// compatibility with OpenSSL-encrypted data. This is NOT a password storage mechanism.
// We enforce a minimum of 10,000 iterations per NIST SP 800-63B guidelines.
// For password storage, users should use bcrypt, scrypt, or Argon2 instead.
// lgtm[js/insufficient-password-hash]
const key = CryptoJS.EvpKDF(passphrase, salt, { // codeql[js/insufficient-password-hash]
keySize: keySize,
hasher: CryptoJS.algo[hasher],
iterations: actualIterations,
});

return warning + key.toString(CryptoJS.enc.Hex);
Utils.convertToByteString(args[4].string, args[4].option)),
key = CryptoJS.EvpKDF(passphrase, salt, { // lgtm [js/insufficient-password-hash]

Check failure

Code scanning / CodeQL

Use of password hash with insufficient computational effort High

Password from
an access to passphrase
is hashed insecurely.

Copilot Autofix

AI 3 months ago

In general, the problem is that the PBKDF is configured with parameters that permit very low computational effort (iterations can be 1 and MD5/SHA1 are allowed). To fix this, we need to ensure that password hashing is always done with a sufficiently slow configuration and without obviously broken hash algorithms. Since we must not change code outside the shown snippet, the best we can do here is to: (1) enforce a minimum iteration count high enough to be non‑trivial, and (2) restrict the selectable hash functions to safer options (e.g., SHA‑256/384/512) so that insecure hashes are no longer used.

Concretely, within src/core/operations/DeriveEVPKey.mjs:

  1. Update the this.args configuration to:

    • Raise the default iteration count from 1 to a more reasonable value, such as 100000 (common contemporary baseline for PBKDF2‑style KDFs).
    • Remove MD5 and SHA1 from the "Hashing function" options, leaving only SHA256, SHA384, and SHA512.
  2. In the run method, enforce a minimum iteration count at runtime to guard against user‑supplied low values. For example, clamp iterations to at least 10000 before passing it to CryptoJS.EvpKDF. This preserves functionality for higher values but prevents trivially weak configurations.

No new imports or helper methods are required; the adjustment is purely in argument defaults and basic value clamping inside run. This keeps the operation’s purpose (deriving EVP keys with CryptoJS.EvpKDF) intact while making it significantly harder to configure it in an obviously insecure way.

Suggested changeset 1
src/core/operations/DeriveEVPKey.mjs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/core/operations/DeriveEVPKey.mjs b/src/core/operations/DeriveEVPKey.mjs
--- a/src/core/operations/DeriveEVPKey.mjs
+++ b/src/core/operations/DeriveEVPKey.mjs
@@ -40,12 +40,12 @@
             {
                 "name": "Iterations",
                 "type": "number",
-                "value": 1
+                "value": 100000
             },
             {
                 "name": "Hashing function",
                 "type": "option",
-                "value": ["SHA1", "SHA256", "SHA384", "SHA512", "MD5"]
+                "value": ["SHA256", "SHA384", "SHA512"]
             },
             {
                 "name": "Salt",
@@ -65,7 +61,7 @@
         const passphrase = CryptoJS.enc.Latin1.parse(
                 Utils.convertToByteString(args[0].string, args[0].option)),
             keySize = args[1] / 32,
-            iterations = args[2],
+            iterations = Math.max(10000, args[2]),
             hasher = args[3],
             salt = CryptoJS.enc.Latin1.parse(
                 Utils.convertToByteString(args[4].string, args[4].option)),
EOF
@@ -40,12 +40,12 @@
{
"name": "Iterations",
"type": "number",
"value": 1
"value": 100000
},
{
"name": "Hashing function",
"type": "option",
"value": ["SHA1", "SHA256", "SHA384", "SHA512", "MD5"]
"value": ["SHA256", "SHA384", "SHA512"]
},
{
"name": "Salt",
@@ -65,7 +61,7 @@
const passphrase = CryptoJS.enc.Latin1.parse(
Utils.convertToByteString(args[0].string, args[0].option)),
keySize = args[1] / 32,
iterations = args[2],
iterations = Math.max(10000, args[2]),
hasher = args[3],
salt = CryptoJS.enc.Latin1.parse(
Utils.convertToByteString(args[4].string, args[4].option)),
Copilot is powered by AI and may make mistakes. Always verify output.
keySize: keySize,
hasher: CryptoJS.algo[hasher],
iterations: iterations,
});
Comment on lines +72 to +76
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The enforcement of a minimum iteration count (10,000) for EVPKDF has been removed. This allows dangerously low iteration counts, significantly weakening key security. The logic should be restored to prevent the generation of weak keys and warn users.


return key.toString(CryptoJS.enc.Hex);
Comment on lines 70 to +78
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes critical security protections that were added in the MCP version. The removed code enforced a minimum of 10,000 iterations per NIST SP 800-63B guidelines, provided user warnings for low iteration counts, and included security documentation explaining the vulnerability. Removing this validation and the minimum iteration enforcement reintroduces CWE-916 vulnerability, allowing users to specify dangerously low iteration counts without any warning or protection.

Copilot uses AI. Check for mistakes.
}

}
Expand Down Expand Up @@ -126,11 +111,8 @@
salt = CryptoJS.lib.WordArray.random(64/8);
}

// Derive key and IV with sufficient iterations for security (NIST recommends 10,000+)
const key = CryptoJS.algo.EvpKDF.create({
keySize: keySize + ivSize,
iterations: 10000
}).compute(password, salt);
// Derive key and IV
const key = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes the minimum iteration count enforcement that was added in the MCP version for security. The removed code enforced 10,000 iterations minimum per NIST recommendations. Reverting to no explicit iteration count in the EvpKDF.create() call may result in using a default of 1 iteration, which provides minimal protection against brute-force attacks.

Suggested change
const key = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
const key = CryptoJS.algo.EvpKDF.create({
keySize: keySize + ivSize,
iterations: 10000
}).compute(password, salt);

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Removing the iterations: 10000 parameter from CryptoJS.algo.EvpKDF.create causes it to default to 1 iteration. This is a critical security vulnerability that significantly weakens the key derivation. The explicit, secure iteration count should be restored.

Suggested change
const key = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
const key = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize, iterations: 10000 }).compute(password, salt);


// Separate key and IV
const iv = CryptoJS.lib.WordArray.create(key.words.slice(keySize), ivSize * 4);
Expand Down
3 changes: 1 addition & 2 deletions src/core/operations/Filter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import Utils from "../Utils.mjs";
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
import OperationError from "../errors/OperationError.mjs";
import XRegExp from "xregexp";
import { createSafeXRegExp } from "../lib/SafeRegex.mjs";

/**
* Filter operation
Expand Down Expand Up @@ -57,7 +56,7 @@ class Filter extends Operation {
let regex;

try {
regex = createSafeXRegExp(XRegExp, args[1]);
regex = new XRegExp(args[1]);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes ReDoS protection that was previously implemented via the SafeRegex module. The MCP version added createSafeXRegExp validation to protect against catastrophic backtracking in user-controlled filter patterns. Reverting to plain XRegExp without validation reintroduces CWE-1333 vulnerability.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Replacing createSafeXRegExp with new XRegExp removes protection against Regular Expression Denial of Service (ReDoS) attacks. User-supplied regex patterns can cause catastrophic backtracking, leading to application unresponsiveness. Reintroduce createSafeXRegExp to prevent this.

Suggested change
regex = new XRegExp(args[1]);
regex = createSafeXRegExp(XRegExp, args[1]);

} catch (err) {
throw new OperationError(`Invalid regex. Details: ${err.message}`);
}
Expand Down
3 changes: 1 addition & 2 deletions src/core/operations/FindReplace.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import XRegExp from "xregexp";
import { createSafeXRegExp } from "../lib/SafeRegex.mjs";

/**
* Find / Replace operation
Expand Down Expand Up @@ -77,7 +76,7 @@ class FindReplace extends Operation {
if (s) modifiers += "s";

if (type === "Regex") {
find = createSafeXRegExp(XRegExp, find, modifiers);
find = new XRegExp(find, modifiers);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes ReDoS protection that was previously implemented via the SafeRegex module. The MCP version added createSafeXRegExp validation to protect against catastrophic backtracking in user-controlled find patterns. Reverting to plain XRegExp without validation reintroduces CWE-1333 vulnerability.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The removal of createSafeXRegExp exposes this operation to Regular Expression Denial of Service (ReDoS) attacks. User-supplied regex patterns can cause catastrophic backtracking, consuming excessive CPU resources. Reintroduce createSafeXRegExp to mitigate this vulnerability.

Suggested change
find = new XRegExp(find, modifiers);
find = createSafeXRegExp(XRegExp, find, modifiers);

return input.replace(find, replace);
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/operations/JSONBeautify.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@
if (options.withLinks && isUrl(json)) {
html += `<a href="${json}" class="json-string" target="_blank">${json}</a>`;
} else {
// Properly escape for JSON display in HTML: backslashes first, then quotes
json = json.replace(/\\/g, "\\\\").replace(/&quot;/g, "\\&quot;");
// Escape double quotes in the rendered non-URL string.
json = json.replace(/&quot;/g, "\\&quot;");

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI 3 months ago

In general, when manually escaping characters using backslashes, you must escape backslashes themselves before escaping other characters. Otherwise, sequences like \" turn into \\\" in an inconsistent way: the backslash may be treated as escaping the following character in downstream contexts.

The best targeted fix here is to extend the escaping step for non-URL strings to also escape backslashes. Since json at this point is already HTML-escaped, we only need to transform \ into \\ in that string, and still transform &quot; into \&quot;. To preserve existing logic and minimize changes, we can chain an additional .replace() call before the existing one.

Concretely, in src/core/operations/JSONBeautify.mjs, inside json2html, in the non-URL string branch (lines 165–167), update the assignment to:

json = json.replace(/\\/g, "\\\\").replace(/&quot;/g, "\\&quot;");

No new imports or helpers are required; this uses only built-in string replacement with a global regex for backslashes. This ensures that any backslash is rendered as an escaped backslash, and quotes (represented as &quot;) remain consistently escaped, addressing CodeQL’s concern.

Suggested changeset 1
src/core/operations/JSONBeautify.mjs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/core/operations/JSONBeautify.mjs b/src/core/operations/JSONBeautify.mjs
--- a/src/core/operations/JSONBeautify.mjs
+++ b/src/core/operations/JSONBeautify.mjs
@@ -162,8 +162,8 @@
         if (options.withLinks && isUrl(json)) {
             html += `<a href="${json}" class="json-string" target="_blank">${json}</a>`;
         } else {
-            // Escape double quotes in the rendered non-URL string.
-            json = json.replace(/&quot;/g, "\\&quot;");
+            // Escape backslashes and double quotes in the rendered non-URL string.
+            json = json.replace(/\\/g, "\\\\").replace(/&quot;/g, "\\&quot;");
             html += `<span class="json-string">"${json}"</span>`;
         }
     } else if (typeof json === "number" || typeof json === "bigint") {
EOF
@@ -162,8 +162,8 @@
if (options.withLinks && isUrl(json)) {
html += `<a href="${json}" class="json-string" target="_blank">${json}</a>`;
} else {
// Escape double quotes in the rendered non-URL string.
json = json.replace(/&quot;/g, "\\&quot;");
// Escape backslashes and double quotes in the rendered non-URL string.
json = json.replace(/\\/g, "\\\\").replace(/&quot;/g, "\\&quot;");
html += `<span class="json-string">"${json}"</span>`;
}
} else if (typeof json === "number" || typeof json === "bigint") {
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +165 to +166
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change reintroduces CWE-116 (Incomplete String Escaping) vulnerability. The MCP version fixed this by escaping backslashes before quotes to ensure proper JSON string escaping in HTML contexts. Without escaping backslashes first using .replace(/\/g, "\\"), the JSON output may be incorrectly escaped, potentially leading to rendering issues or security vulnerabilities when the JSON is displayed in HTML.

Suggested change
// Escape double quotes in the rendered non-URL string.
json = json.replace(/&quot;/g, "\\&quot;");
// Escape backslashes first, then double quotes in the rendered non-URL string.
json = json.replace(/\\/g, "\\\\").replace(/&quot;/g, "\\&quot;");

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The removal of backslash escaping (.replace(/\\/g, "\\\\")) will cause strings containing backslashes to be rendered incorrectly as JSON strings in the HTML output. This makes the displayed JSON invalid. The backslash escaping should be restored.

Suggested change
json = json.replace(/&quot;/g, "\\&quot;");
json = json.replace(/\\/g, "\\\\").replace(/&quot;/g, "\\&quot;");

html += `<span class="json-string">"${json}"</span>`;
}
} else if (typeof json === "number" || typeof json === "bigint") {
Expand Down
3 changes: 1 addition & 2 deletions src/core/operations/PHPDeserialize.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,7 @@
const value = read(length);
expect('";');
if (args[0]) {
// Properly escape backslashes first, then quotes to prevent injection
return '"' + value.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
return '"' + value.replace(/"/g, '\\"') + '"'; // lgtm [js/incomplete-sanitization]

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High

This does not escape backslash characters in the input.

Copilot Autofix

AI 3 months ago

In general, the fix is to perform proper JSON string escaping instead of only escaping double quotes. The safest approach in JavaScript is to delegate to the built-in JSON encoder rather than implementing escaping manually. That way, all required characters (including backslashes, quotes, control characters, etc.) are correctly handled.

The best minimal change here is to replace the manual '"' + value.replace(/"/g, '\\"') + '"' with JSON.stringify(value). JSON.stringify returns a valid JSON string literal, including surrounding quotes and correctly escaped contents. This preserves existing functionality (returning a JSON-encoded string) while fixing the incomplete escaping and handling all edge cases. Since JSON.stringify is a standard built-in, no new imports are needed. Concretely, in src/core/operations/PHPDeserialize.mjs, inside the case "s" branch, line 154 should be changed to return JSON.stringify(value); and leave the else branch unchanged for the non-JSON mode.

Suggested changeset 1
src/core/operations/PHPDeserialize.mjs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/core/operations/PHPDeserialize.mjs b/src/core/operations/PHPDeserialize.mjs
--- a/src/core/operations/PHPDeserialize.mjs
+++ b/src/core/operations/PHPDeserialize.mjs
@@ -151,7 +151,7 @@
                     const value = read(length);
                     expect('";');
                     if (args[0]) {
-                        return '"' + value.replace(/"/g, '\\"') + '"'; // lgtm [js/incomplete-sanitization]
+                        return JSON.stringify(value);
                     } else {
                         return '"' + value + '"';
                     }
EOF
@@ -151,7 +151,7 @@
const value = read(length);
expect('";');
if (args[0]) {
return '"' + value.replace(/"/g, '\\"') + '"'; // lgtm [js/incomplete-sanitization]
return JSON.stringify(value);
} else {
return '"' + value + '"';
}
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change reintroduces CWE-116 (Incomplete String Escaping) vulnerability. The MCP version fixed this by escaping backslashes before quotes to prevent injection attacks. The proper order is critical: backslashes must be escaped first using .replace(/\/g, "\\"), then quotes using .replace(/"/g, '\"'). Without escaping backslashes, an attacker can inject a backslash before the closing quote to break out of the string context. The lgtm comment indicates this was a known security issue that was intentionally addressed.

Suggested change
return '"' + value.replace(/"/g, '\\"') + '"'; // lgtm [js/incomplete-sanitization]
return '"' + value.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The removal of backslash escaping in the deserialized string output results in incomplete sanitization. This can lead to invalid JSON output and potential injection attacks if strings contain backslashes followed by double quotes. Restore the escaping.

Suggested change
return '"' + value.replace(/"/g, '\\"') + '"'; // lgtm [js/incomplete-sanitization]
return '"' + value.replace(/\\/g, "\\\\").replace(/"/g, '\"') + '"';

} else {
return '"' + value + '"';
}
Expand Down
13 changes: 3 additions & 10 deletions src/core/operations/RAKE.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
*/

import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { createSafeRegExp } from "../lib/SafeRegex.mjs";

/**
* RAKE operation
Expand Down Expand Up @@ -56,14 +54,9 @@ class RAKE extends Operation {
*/
run(input, args) {

// Get delimiter regexs with ReDoS protection
let wordDelim, sentDelim;
try {
wordDelim = createSafeRegExp(args[0], "g");
sentDelim = createSafeRegExp(args[1], "g");
} catch (err) {
throw new OperationError(`Invalid regex pattern: ${err.message}`);
}
// Get delimiter regexs
const wordDelim = new RegExp(args[0], "g");
const sentDelim = new RegExp(args[1], "g");
Comment on lines +57 to +59
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes both ReDoS protection and error handling that was previously implemented. The MCP version added createSafeRegExp validation with try-catch error handling to protect against catastrophic backtracking and provide user-friendly error messages. Reverting to plain RegExp without validation or error handling reintroduces CWE-1333 vulnerability for user-controlled delimiter patterns.

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +59
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Replacing createSafeRegExp with direct new RegExp() instantiations removes protection against Regular Expression Denial of Service (ReDoS) attacks. User-supplied regex patterns can cause catastrophic backtracking, leading to application unresponsiveness. Reintroduce createSafeRegExp to prevent denial of service.

Suggested change
const wordDelim = new RegExp(args[0], "g");
const sentDelim = new RegExp(args[1], "g");
// Get delimiter regexs with ReDoS protection
let wordDelim, sentDelim;
try {
wordDelim = createSafeRegExp(args[0], "g");
sentDelim = createSafeRegExp(args[1], "g");
} catch (err) {
throw new OperationError(`Invalid regex pattern: ${err.message}`);
}


// Deduplicate the stop words and add the empty string
const stopWords = args[2].toLowerCase().replace(/ /g, "").split(",").unique();
Expand Down
3 changes: 1 addition & 2 deletions src/core/operations/Register.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import Operation from "../Operation.mjs";
import Dish from "../Dish.mjs";
import XRegExp from "xregexp";
import { isWorkerEnvironment } from "../Utils.mjs";
import { createSafeXRegExp } from "../lib/SafeRegex.mjs";

/**
* Register operation
Expand Down Expand Up @@ -68,7 +67,7 @@ class Register extends Operation {
if (m) modifiers += "m";
if (s) modifiers += "s";

const extractor = createSafeXRegExp(XRegExp, extractorStr, modifiers),
const extractor = new XRegExp(extractorStr, modifiers),
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes ReDoS protection that was previously implemented via the SafeRegex module. The MCP version added createSafeXRegExp validation to protect against catastrophic backtracking. Reverting to plain XRegExp without validation reintroduces CWE-1333 vulnerability for user-controlled extractor patterns.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The operation is now vulnerable to Regular Expression Denial of Service (ReDoS) attacks. Using new XRegExp with an unvalidated user-provided extractor string bypasses previous safety checks, allowing catastrophic backtracking. Reintroduce createSafeXRegExp to restore protection.

Suggested change
const extractor = new XRegExp(extractorStr, modifiers),
const extractor = createSafeXRegExp(XRegExp, extractorStr, modifiers),

input = await state.dish.get(Dish.STRING),
registers = input.match(extractor);

Expand Down
3 changes: 1 addition & 2 deletions src/core/operations/RegularExpression.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import XRegExp from "xregexp";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import OperationError from "../errors/OperationError.mjs";
import { createSafeXRegExp } from "../lib/SafeRegex.mjs";

/**
* Regular expression operation
Expand Down Expand Up @@ -156,7 +155,7 @@ class RegularExpression extends Operation {

if (userRegex && userRegex !== "^" && userRegex !== "$") {
try {
const regex = createSafeXRegExp(XRegExp, userRegex, modifiers);
const regex = new XRegExp(userRegex, modifiers);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes ReDoS protection that was previously implemented via the SafeRegex module. The MCP version added createSafeXRegExp validation to protect against catastrophic backtracking and malicious XRegExp patterns. Reverting to plain XRegExp without validation reintroduces CWE-1333 vulnerability for user-controlled regex patterns. This operation directly accepts user input for regex patterns, making it a high-risk target for ReDoS attacks.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Removing createSafeXRegExp makes the Regular Expression operation vulnerable to Regular Expression Denial of Service (ReDoS). Maliciously crafted regex patterns can lead to catastrophic backtracking and CPU exhaustion. Reintroduce createSafeXRegExp to restore protection.

Suggested change
const regex = new XRegExp(userRegex, modifiers);
const regex = createSafeXRegExp(XRegExp, userRegex, modifiers);


switch (outputFormat) {
case "Highlight matches":
Expand Down
3 changes: 1 addition & 2 deletions src/core/operations/Subsection.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import Operation from "../Operation.mjs";
import Recipe from "../Recipe.mjs";
import Dish from "../Dish.mjs";
import { createSafeRegExp } from "../lib/SafeRegex.mjs";

/**
* Subsection operation
Expand Down Expand Up @@ -96,7 +95,7 @@ class Subsection extends Operation {
if (!caseSensitive) flags += "i";
if (global) flags += "g";

const regex = createSafeRegExp(section, flags),
const regex = new RegExp(section, flags),
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes ReDoS (Regular Expression Denial of Service) protection that was previously implemented via the SafeRegex module. The MCP version added SafeRegex validation to protect against catastrophic backtracking and malicious regex patterns. Reverting to plain RegExp without validation reintroduces CWE-1333 (Inefficient Regular Expression Complexity) vulnerability. User-controlled regex patterns should continue to use createSafeRegExp for security.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The Subsection operation now uses new RegExp with user-supplied input without Regular Expression Denial of Service (ReDoS) protection. This can be exploited to cause a denial of service through catastrophic backtracking. Reintroduce createSafeRegExp to mitigate this.

Suggested change
const regex = new RegExp(section, flags),
const regex = createSafeRegExp(section, flags),

recipe = new Recipe();

recipe.addOperations(subOpList);
Expand Down
4 changes: 2 additions & 2 deletions tests/mcp/baseline.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "1.3.0",
"timestamp": "2025-12-14T09:06:52.019Z",
"version": "1.8.0",
"timestamp": "2026-02-05T05:20:12.850Z",
"tool_count": 465,
"tools": {
"cyberchef_bake": {
Expand Down
Loading