[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#927959: unblock: node-fresh/0.2.0-2



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package node-fresh

Hi all,

node-fresh is vulnerable to CVE-2017-16119 (#927715). Vulnerability is
due to Node.js regexp parsing DDOS. I imported and adapted upstream
patch to workaround this issue and enabled upstream tests in both build
and autopkgtest. Full changes:
  * Declare compliance with policy 4.3.0
  * Change section to javascript
  * Change priority to optional
  * Add upstream/metadata
  * Add patch to fix regexp ddos (Closes: #927715, CVE-2017-16119)
  * Fix and enable upstream test using pkg-js-tools
  * Fix VCS fields
  * Fix copyright format URL

Reverse dependencies:
 - node-serve-favicon
 - node-send -------------+
   +-> node-serve-static -+
 - node-express <---------+

I enabled upstream test to verify that there is no regression and tested
build and tests of node-serve-static, node-send and node-express (using
additional needed modules). I plan to upload a new node-express in
experimental with tests enabled to see autopkgtest regression if any.

Cheers,
Xavier

unblock node-fresh/0.2.0-2
diff --git a/debian/changelog b/debian/changelog
index e827b8b..6a067b4 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+node-fresh (0.2.0-2) unstable; urgency=medium
+
+  * Team upload
+  * Declare compliance with policy 4.3.0
+  * Change section to javascript
+  * Change priority to optional
+  * Add upstream/metadata
+  * Add patch to fix regexp ddos (Closes: #927715, CVE-2017-16119)
+  * Fix and enable upstream test using pkg-js-tools
+  * Fix VCS fields
+  * Fix copyright format URL
+
+ -- Xavier Guimard <yadd@debian.org>  Thu, 25 Apr 2019 12:23:28 +0200
+
 node-fresh (0.2.0-1) unstable; urgency=low
 
   * Initial release (Closes: #727797)
diff --git a/debian/control b/debian/control
index ebd5a5e..efddc65 100644
--- a/debian/control
+++ b/debian/control
@@ -1,16 +1,19 @@
 Source: node-fresh
-Section: web
-Priority: extra
+Section: javascript
+Priority: optional
 Maintainer: Debian Javascript Maintainers <pkg-javascript-devel@lists.alioth.debian.org>
 Uploaders: Jérémy Lal <kapouer@melix.org>
+Testsuite: autopkgtest-pkg-nodejs
 Build-Depends:
  debhelper (>= 8.0.0)
  , dh-buildinfo
+ , mocha
  , nodejs
-Standards-Version: 3.9.4
+ , pkg-js-tools
+Standards-Version: 4.3.0
+Vcs-Browser: https://salsa.debian.org/js-team/node-fresh
+Vcs-Git: https://salsa.debian.org/js-team/node-fresh.git
 Homepage: https://github.com/visionmedia/node-fresh
-Vcs-Git: git://anonscm.debian.org/collab-maint/node-fresh.git
-Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/node-fresh.git
 
 Package: node-fresh
 Architecture: all
@@ -23,4 +26,3 @@ Description: Check client cache staleness using HTTP headers - Node.js module
  determine if the client requesting the resource has a stale or fresh cache.
  .
  Node.js is an event-based server-side javascript engine.
-
diff --git a/debian/copyright b/debian/copyright
index 0c7fd09..af7dcf0 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,4 +1,4 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 Upstream-Name: fresh
 
 Files: *
@@ -25,4 +25,3 @@ License: Expat
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
-
diff --git a/debian/patches/CVE-2017-16119.diff b/debian/patches/CVE-2017-16119.diff
new file mode 100644
index 0000000..6461542
--- /dev/null
+++ b/debian/patches/CVE-2017-16119.diff
@@ -0,0 +1,85 @@
+Description: Fix for CVE-2017-16119
+Author: Xavier Guimard <yadd@debian.org>
+Origin: upstream, https://github.com/jshttp/fresh/commit/21a0f0c2a5f447e0d40bc16be0c23fa98a7b46ec
+Bug: https://www.npmjs.com/advisories/526
+Bug-Debian: https://bugs.debian.org/927715
+Forwarded: not-needed
+Last-Update: 2019-04-25
+
+--- a/index.js
++++ b/index.js
+@@ -36,11 +36,27 @@
+   // check for no-cache cache request directive
+   if (cc && cc.indexOf('no-cache') !== -1) return false;  
+ 
+-  // parse if-none-match
+-  if (noneMatch) noneMatch = noneMatch.split(/ *, */);
++  // parse if-none-match and etag
++  if (noneMatch && noneMatch !== '*') {
+ 
+-  // if-none-match
+-  if (noneMatch) etagMatches = ~noneMatch.indexOf(etag) || '*' == noneMatch[0];
++    if (!etag) {
++      return false
++    }
++
++    var etagStale = true
++    var matches = parseTokenList(noneMatch)
++    for (var i = 0; i < matches.length; i++) {
++      var match = matches[i]
++      if (match === etag || match === 'W/' + etag || 'W/' + match === etag) {
++        etagStale = false
++        break
++      }
++    }
++
++    if (etagStale) {
++      return false
++    }
++  }
+ 
+   // if-modified-since
+   if (modifiedSince) {
+@@ -50,4 +66,40 @@
+   }
+ 
+   return !! (etagMatches && notModified);
+-}
+\ No newline at end of file
++}
++
++/**
++ * Parse a HTTP token list.
++ *
++ * @param {string} str
++ * @private
++ */
++
++function parseTokenList (str) {
++  var end = 0
++  var list = []
++  var start = 0
++
++  // gather tokens
++  for (var i = 0, len = str.length; i < len; i++) {
++    switch (str.charCodeAt(i)) {
++      case 0x20: /*   */
++        if (start === end) {
++          start = end = i + 1
++        }
++        break
++      case 0x2c: /* , */
++        list.push(str.substring(start, end))
++        start = end = i + 1
++        break
++      default:
++        end = i + 1
++        break
++    }
++  }
++
++  // final token
++  list.push(str.substring(start, end))
++
++  return list
++}
diff --git a/debian/patches/fix-tests.diff b/debian/patches/fix-tests.diff
new file mode 100644
index 0000000..4a7bbb6
--- /dev/null
+++ b/debian/patches/fix-tests.diff
@@ -0,0 +1,147 @@
+Description: Fix tests
+Author: Xavier Guimard <yadd@debian.org>
+Forwarded: not-needed
+Last-Update: 2019-04-25
+
+--- a/test/fresh.js
++++ b/test/fresh.js
+@@ -1,12 +1,13 @@
+ 
+ var fresh = require('..');
++var assert = require('assert');
+ 
+ describe('fresh(reqHeader, resHeader)', function(){
+   describe('when a non-conditional GET is performed', function(){
+     it('should be stale', function(){
+       var req = {};
+       var res = {};
+-      fresh(req, res).should.be.false;
++      assert.equal(fresh(req, res),false);
+     })
+   })
+ 
+@@ -15,7 +16,7 @@
+       it('should be fresh', function(){
+         var req = { 'if-none-match': 'tobi' };
+         var res = { 'etag': 'tobi' };
+-        fresh(req, res).should.be.true;
++        assert.equal(fresh(req, res),true);
+       })
+     })
+ 
+@@ -23,7 +24,7 @@
+       it('should be stale', function(){
+         var req = { 'if-none-match': 'tobi' };
+         var res = { 'etag': 'luna' };
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+       })
+     })
+ 
+@@ -31,7 +32,7 @@
+       it('should be stale', function(){
+         var req = { 'if-none-match': 'tobi' };
+         var res = {};
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+       })
+     })
+ 
+@@ -39,7 +40,7 @@
+       it('should be fresh', function(){
+         var req = { 'if-none-match': '*' };
+         var res = { 'etag': 'hey' };
+-        fresh(req, res).should.be.true;
++        assert.equal(fresh(req, res),true);
+       })
+     })
+   })
+@@ -50,7 +51,7 @@
+         var now = new Date;
+         var req = { 'if-modified-since': new Date(now - 4000).toUTCString() };
+         var res = { 'last-modified': new Date(now - 2000).toUTCString() };
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+       })
+     })
+ 
+@@ -59,7 +60,7 @@
+         var now = new Date;
+         var req = { 'if-modified-since': new Date(now - 2000).toUTCString() };
+         var res = { 'last-modified': new Date(now - 4000).toUTCString() };
+-        fresh(req, res).should.be.true;
++        assert.equal(fresh(req, res),true);
+       })
+     })
+ 
+@@ -67,7 +68,7 @@
+       it('should be stale', function(){
+         var req = { 'if-none-match': new Date().toUTCString() };
+         var res = {};
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+       })
+     })
+     
+@@ -75,7 +76,7 @@
+       it('should be stale', function(){
+         var req = { 'if-none-match': 'foo' };
+         var res = {};
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+       })
+     })
+ 
+@@ -83,7 +84,7 @@
+       it('should be stale', function(){
+         var req = { 'if-none-match': new Date().toUTCString() };
+         var res = { 'modified-since': 'foo' };
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+       })
+     })
+   })
+@@ -94,7 +95,7 @@
+         var now = new Date;
+         var req = { 'if-none-match': 'tobi', 'if-modified-since': new Date(now - 2000).toUTCString() };
+         var res = { 'etag': 'tobi', 'last-modified': new Date(now - 4000).toUTCString() };
+-        fresh(req, res).should.be.true;
++        assert.equal(fresh(req, res),true);
+       })
+     })
+ 
+@@ -103,12 +104,12 @@
+         var now = new Date;
+         var req = { 'if-none-match': 'tobi', 'if-modified-since': new Date(now - 4000).toUTCString() };
+         var res = { 'etag': 'tobi', 'last-modified': new Date(now - 2000).toUTCString() };
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+ 
+         var now = new Date;
+         var req = { 'if-none-match': 'tobi', 'if-modified-since': new Date(now - 2000).toUTCString() };
+         var res = { 'etag': 'luna', 'last-modified': new Date(now - 4000).toUTCString() };
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+       })
+     })
+ 
+@@ -117,7 +118,7 @@
+         var now = new Date;
+         var req = { 'if-none-match': 'tobi', 'if-modified-since': new Date(now - 4000).toUTCString() };
+         var res = { 'etag': 'luna', 'last-modified': new Date(now - 2000).toUTCString() };
+-        fresh(req, res).should.be.false;
++        assert.equal(fresh(req, res),false);
+       })
+     })
+   })
+@@ -126,7 +127,7 @@
+     it('should be stale', function(){
+       var req = { 'cache-control' : ' no-cache' };
+       var res = {};
+-      fresh(req, res).should.be.false;
++      assert.equal(fresh(req, res),false);
+     })
+   })
+-})
+\ No newline at end of file
++})
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..33b1987
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,2 @@
+CVE-2017-16119.diff
+fix-tests.diff
diff --git a/debian/rules b/debian/rules
index d1fde4f..8b30b10 100755
--- a/debian/rules
+++ b/debian/rules
@@ -5,8 +5,6 @@
 #export DH_VERBOSE=1
 
 %:
-	dh $@
+	dh $@ --with nodejs
 
 override_dh_auto_build:
-override_dh_auto_test:
-
diff --git a/debian/tests/pkg-js/test b/debian/tests/pkg-js/test
new file mode 100644
index 0000000..2b1fda9
--- /dev/null
+++ b/debian/tests/pkg-js/test
@@ -0,0 +1 @@
+mocha --timeout 10000 test
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
new file mode 100644
index 0000000..0e09ab2
--- /dev/null
+++ b/debian/upstream/metadata
@@ -0,0 +1,7 @@
+---
+Archive: GitHub
+Bug-Database: https://github.com/visionmedia/node-fresh/issues
+Contact: https://github.com/visionmedia/node-fresh/issues
+Name: node-fresh
+Repository: https://github.com/visionmedia/node-fresh.git
+Repository-Browse: https://github.com/visionmedia/node-fresh

Reply to: