Skip to content

Commit

Permalink
backport fix to potential regexp DDOS
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiosantoscode committed Apr 28, 2022
1 parent 504b967 commit d8cc569
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 7 deletions.
6 changes: 4 additions & 2 deletions lib/compress/index.js
Expand Up @@ -60,7 +60,8 @@ import {
return_true,
string_template,
regexp_source_fix,
has_annotation
has_annotation,
regexp_is_safe,
} from "../utils/index.js";
import { first_in_statement, } from "../utils/first_in_statement.js";
import {
Expand Down Expand Up @@ -2819,7 +2820,7 @@ var static_fns = convert_to_predicate({
def_eval(AST_BigInt, return_this);
def_eval(AST_RegExp, function(compressor) {
let evaluated = compressor.evaluated_regexps.get(this);
if (evaluated === undefined) {
if (evaluated === undefined && regexp_is_safe(this.value.source)) {
try {
evaluated = (0, eval)(this.print_to_string());
} catch (e) {
Expand Down Expand Up @@ -5089,6 +5090,7 @@ def_optimize(AST_Call, function(self, compressor) {
params.push(value);
return arg !== value;
})
&& regexp_is_safe(params[0])
) {
let [ source, flags ] = params;
source = regexp_source_fix(new RegExp(source).source);
Expand Down
10 changes: 9 additions & 1 deletion lib/utils/index.js
Expand Up @@ -239,7 +239,15 @@ function regexp_source_fix(source) {
return (escaped ? "" : "\\") + lineTerminatorEscape[match];
});
}
const all_flags = "gimuy";

// Subset of regexps that is not going to cause regexp based DDOS
// https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
const re_safe_regexp = /^[\\/|\0\s\w^$.[\]()]*$/;

/** Check if the regexp is safe for Terser to create without risking a RegExp DOS */
export const regexp_is_safe = (source) => re_safe_regexp.test(source);

const all_flags = "dgimsuy";
function sort_regexp_flags(flags) {
const existing_flags = new Set(flags.split(""));
let out = "";
Expand Down
21 changes: 17 additions & 4 deletions test/compress/regexp.js
Expand Up @@ -30,10 +30,10 @@ regexp_2: {
unsafe: true,
}
input: {
console.log(JSON.stringify("COMPASS? Overpass.".match(new RegExp("([Sap]+)", "ig"))));
console.log(JSON.stringify("COMPASS? Overpass.".match(new RegExp("(pass)", "ig"))));
}
expect: {
console.log(JSON.stringify("COMPASS? Overpass.".match(/([Sap]+)/gi)));
console.log(JSON.stringify("COMPASS? Overpass.".match(/(pass)/gi)));
}
expect_stdout: '["PASS","pass"]'
}
Expand All @@ -44,10 +44,10 @@ unsafe_slashes: {
unsafe: true
}
input: {
console.log(new RegExp("^https://"))
console.log(new RegExp("^https//"))
}
expect: {
console.log(/^https:\/\//)
console.log(/^https\/\//)
}
}

Expand All @@ -63,3 +63,16 @@ inline_script: {
}
expect_exact: '/* <\\/script> */\n/[<\\/script>]/;'
}

regexp_no_ddos: {
options = { unsafe: true, evaluate: true }
input: {
console.log(/(b+)b+/.test("bbb"))
console.log(RegExp("(b+)b+").test("bbb"))
}
expect: {
console.log(/(b+)b+/.test("bbb"))
console.log(RegExp("(b+)b+").test("bbb"))
}
expect_stdout: ["true", "true"]
}

1 comment on commit d8cc569

@manda2020panda
Copy link

Choose a reason for hiding this comment

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

..

Please sign in to comment.