False positive regex DoS vulnerability?

  • Enterprise Edition Version 10.2.1 (build 78527)
    Why is SonarQube alerting a vulnerability for the following straightforward regex?

/[^.]+.company-qa.com/
Make sure the regex used here, which is vulnerable to super-linear runtime due to backtracking, cannot lead to denial of service.

Is this a false positive SonarQube bug?

Hello Barnaby!

Thank you very much for your Feedback and welcome to our community!
I am sorry, but I can not reproduce this behavior. I tested it with SonarQube 10.2.1 (build 78527) in some simple Java code and no issue for rule S5852 was raised. Here you can see that I also ran the same code on SonarCloud and no Security Hotspot was identified.

It looks like I need more context to help you. Without any additional context your regex /[^.]+.company-qa.com/ seems to be safe.
As a side note: You may want to escape the “.” e.g.: [^.]+\.company-qa\.com

Kind regards,
Daniel

1 Like

Thanks Daniel, I appreciate it. The only other context I think I could give, and should have done so originally, is that the code is Typescript (although, in this case I don’t think that would matter at all). Let me know what you think. Thanks for your help!!

The code looks something like this: (for context, see the regex here)

    const domainMap = new Map<RegExp, any>([
      [
        /(app|us02|api-sandbox-time|sandbox-time-us02|sandbox)\.company\.com/,
        prodEnvVar,
      ],
      [/[^.]+\.company-qa\.com/, stagingEnvVar],
    ]);

Hi Barnaby,

thanks for the additional context! I misinterpreted your regex and thought the leading and trailing / were part of it.

This regex [^.]+\.company-qa\.com can have quadratic (so more than linear) execution time and it also raises for S5852 in Java. The reason here is, that it is not anchored AND has a greedy quantifier.

What could happen is, that the regex will first be applied to the input starting from the first character. Because of the greedy quantifier, this single run has a linear runtime (backtracking). If it is not successful the regex is applied starting from the second character and so on (so there is a linear amount of runs). All in all, this could lead to a quadratic runtime.

As a solution, you can either:

  1. Anchor the regex (add a prefix that has to match before looking for [^.]+)
  2. Make the quantifier possessive ([^.]++) so that it won’t give back and therefore does not backtrack
  3. Set a maximum for how many characters can be matched by the quantifier (e.g. [^.]{1,50})

You could even combine options 2 and 3 to have a possessive quantifier with a maximum ([^.]{1,50}+).

I think a possessive quantifier is a good option since the token after the quantifier is mutually exclusive with the token before it ([^.] can never match \.) so backtracking won’t find any additional matches.

I hope this helps you to fix the issue.

Best regards,
Daniel

1 Like