javascriptnode.jsnpmminimatch

What is the "RegExp DoS issue"?


I just installed nodejs in a server and a basic npm install shows a lot of messages like this:

$ npm install
npm WARN deprecated minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated minimatch@0.2.14: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated graceful-fs@1.2.3: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.
npm WARN deprecated graceful-fs@2.0.3: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.
npm WARN prefer global node-gyp@3.4.0 should be installed with -g

Note the message appearing to the right:

npm WARN ... or higher to avoid a RegExp DoS issue
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^

In my local server, I was already using minimatch 3.0.3. However, since the server was not using the last version of node, this is new to me and started to investigate:

This issue being reported in npm's github and mentions to it in other questions. In general, it gets solved by upgrading the version of minimatch to at least 3.0.2.

However, I wonder what is this RegExp DoS issue? Is there any specific regex that was allowing a DoS attack through minimatch? I cannot imagine how this could happen and don't want to reproduce it, but I fail to find more documentation and minimatch's Github list of issues does not have any trace of it.

From the releases pages I see the only commit for the 3.0.2 release, in which basically the regex syntax is being encapsulated (I am not familiar enough with JavaScript to follow all of it to the last tiny detail).


Solution

  • From the commit you link to (https://github.com/isaacs/minimatch/commit/6944abf9e0694bd22fd9dad293faa40c2bc8a955):

    The test added in the commit is making a regex like this:

    var exploit = '!(' + genstr(1024 * 15, '\\') + 'A)'
    

    That is creating a string starting '!(', then 1024*15 copies of \, then 'A)'. That must be the DoS condition.

    This line

    tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
    

    is probably the one that was choking.