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 addingu
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