JavaScript Analyzer Updates - May 2021

In the latest release of the JavaScript analyzer, we have added support for 8 new autofixes!
The release also adds a security issue to detect ReDoS vulnerability, and fixes the false positive in an issue you reported!

Here is the detailed changelog:

New issue: Regular Expression Denial of Service (ReDoS)

This issue checks for possible regular expression DoS vulnerability

The Regular expression Denial of Service (ReDoS) is a Denial of Service attack that exploits the fact that most Regular Expression implementations may reach extreme situations that cause them to work very slowly (exponentially related to input size).

An attacker can then cause a regular expression program to enter these extreme situations and hang for a very long time.

How to identify an unsafe pattern?

If any Regex pattern contains the following characteristics, then it is considered to be unsafe:

  • Grouping constructs with repetition of pattern
  • Inside the repeated group there should appear
    • Repetition of regex pattern
    • Alternation with overlapping of regex patterns

Examples of Invalid code

(a+)+
([a-zA-Z]+)*
(a|aa)+
(a|a?)+
(.*a){x} for x \> 10

All the above are susceptible to the input aaaaaaaaaaaaaaaaaaaaaaaa! (The minimum input length might change when using faster or slower machines).

Why do these regex matches take so long?

Most regex engines use a naive backtracking algorithm that works something like this:

  • Match characters as you would expect.
  • Any time you have a choice, try one path. If it doesn’t work, try the other one later.
  • If you find a match, return success.

This algorithm means that if there are more than a linear number of possible paths to try, then the regex engine will take more than linear time.

How to fix ReDoS regexes?

Developers used one of three strategies:

  • Trim Don’t touch the regex. Just trim the input, so it’s not too long, thus bounding the worst-case behavior. This works OK provided that (1) legitimate input shouldn’t be “too long” (e.g., 500 characters?); and (2) the worst-case behavior is not exponential.
  • Revise Tweak the regex, so it is no longer vulnerable to ReDoS, but it still matches the same language. Or similar. Be careful — we saw several cases where a revised regex became safe to one input but vulnerable to new input.
  • Replace Replace the regex with string operations.

Use safe regex engines

Instead of using built-in, unsafe regex engines (like the Node.js regex engine), you can opt to use safe alternatives instead. For example, re2 is a safe alternative that you can use without fear of ReDoS.

New Autofixes

1. JS-0093 : Avoid having unused expressions

Removes the reported unused expression

  • Before Autofix:

    a() && b
    function foo() {
      'directive one'
      f()
      ;('directive two')
    }
    {
      0
    }
    
  • After Autofix:

    // empty here
    function foo() {
      'directive one'
      f()
    }
    {
    }
    

2. JS-0728 : Avoid using deprecated template lifecycle callback assignments

Replaces the deprecated method with a valid method

  • Before Autofix:

    Template.foo.created = function { /* .. */ }
    Template.foo.rendered = function { /* .. */ }
    Template.foo.destroyed = function { /* .. */ }
    
    Template[bar].created = function { /* .. */ }
    Template[bar].rendered = function { /* .. */ }
    Template[bar].destroyed = function { /* .. */ }
    
  • After Autofix:

    Template.foo.onCreated(function { /* .. */ })
    Template.foo.onRendered(function { /* .. */ })
    Template.foo.ondestroyed(function { /* .. */ })
    
    Template[foo].onCreated(function { /* .. */ })
    Template[foo].onRendered(function { /* .. */ })
    Template[foo].ondestroyed(function { /* .. */ })
    

3. JS-0757 : Prefer that autoFocus prop is not used on elements for JSX

Removes the autofocus property

  • Before Autofix:

    <div autoFocus />
    <label autoFocus="true" />
    <a autoFocus="false" />
    <p autoFocus={undefined} />
    
  • After Autofix:

    <div  />
    <label  />
    <a  />
    <p  />
    

4. JS-0822 : Detected calls to buffer with noAssert flag set

Removes the noAssert argument from the buffer method

  • Before Autofix:

    buf.readUInt8(0, true)
    buf.writeUInt8(0x3, 0, true)
    
  • After Autofix:

    buf.readUInt8(0)
    buf.writeUInt8(0x3, 0)
    

5. JS-0025 : Detected unreachable code

Removes the reported unreachable code

  • Before Autofix:

    function foo() {
      return x
      var x = 1
    }
    
  • After Autofix:

    function foo() {
      return x
    }
    

6. JS-0008 : Found duplicate switch case condition

Removes the later found switch case

  • Before Autofix:

    switch (a) {
      case 1:
        break
      case 2:
        break
      case 1: // duplicate test expression
        break
      default:
        break
    }
    
  • After Autofix:

    switch (a) {
      case 1:
        break
      case 2:
        break
    
      default:
        break
    }
    

7. JS-0508 : Use $Exact to make type spreading safe

Adds a $Exact wrap around the spreading

  • Before Autofix:

    type bar = { ...{ test: string } }
    
    type foo = { test: number }
    type bar = { ...foo }
    
  • After Autofix:

    type bar = { ...$Exact<{ test: string }> }
    
    type foo = { test: number }
    type bar = { ...$Exact<foo> }
    

8. JS-0329 : Prefer iterating over an array with a for-of loop instead of for-in

Replaces for-in with for-of

  • Before Autofix:

    for (const x in [3, 4, 5]) {
      console.log(x)
    }
    
  • After Autofix:

    for (const x of [3, 4, 5]) {
      console.log(x)
    }
    

False-positive fix:

  • JS-0117 : Prefer adding u flag in regular expressions

Earlier this issue was reported for all regular expressions that don’t contain u (unicode) flag.
After this fix, this issue will be raised only when:

  • The regular expression contains unicode property escapes i.e \p{<property-name>}

    What is Unicode property escapes ? Unicode property escapes Regular Expressions allow for matching characters based on their Unicode properties. A character is described by several properties which are either binary (“boolean-like”) or non-binary. For instance, Unicode property escapes can be used to match emojis, punctuations, letters (even letters from specific languages or scripts), etc. Read more here.

  • The regular expression contains 4 bytes characters like emojis or some special characters

2 Likes