High severity7.5NVD Advisory· Published Apr 13, 2016· Updated May 6, 2026
CVE-2016-2515
CVE-2016-2515
Description
Hawk before 3.1.3 and 4.x before 4.1.1 allow remote attackers to cause a denial of service (CPU consumption or partial outage) via a long (1) header or (2) URI that is matched against an improper regular expression.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
hawknpm | >= 4.0.0, < 4.1.1 | 4.1.1 |
hawknpm | < 3.1.3 | 3.1.3 |
Affected products
2cpe:2.3:a:hawk_project:hawk:3.1.2:*:*:*:*:*:*:*+ 1 more
- cpe:2.3:a:hawk_project:hawk:3.1.2:*:*:*:*:*:*:*
- cpe:2.3:a:hawk_project:hawk:4.1.0:*:*:*:*:*:*:*
Patches
10833f99ba645Fix minor DoS attack on long headers or uris. Closes #168
5 files changed · +86 −6
lib/server.js+10 −2 modified@@ -310,6 +310,11 @@ exports.header = function (credentials, artifacts, options) { * 'hostHeaderName', 'localtimeOffsetMsec', 'host', 'port' */ + +// 1 2 3 4 +internals.bewitRegex = /^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/; + + exports.authenticateBewit = function (req, credentialsFunc, options, callback) { callback = Hoek.nextTick(callback); @@ -327,8 +332,11 @@ exports.authenticateBewit = function (req, credentialsFunc, options, callback) { // Extract bewit - // 1 2 3 4 - const resource = request.url.match(/^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/); + if (request.url.length > Utils.limits.maxMatchLength) { + return callback(Boom.badRequest('Resource path exceeds max length')); + } + + const resource = request.url.match(internals.bewitRegex); if (!resource) { return callback(Utils.unauthorized()); }
lib/utils.js+20 −3 modified@@ -17,6 +17,11 @@ exports.version = function () { }; +exports.limits = { + maxMatchLength: 4096 // Limit the length of uris and headers to avoid a DoS attack on string matching +}; + + // Extract host and port from request // $1 $2 @@ -31,6 +36,10 @@ exports.parseHost = function (req, hostHeaderName) { return null; } + if (hostHeader.length > exports.limits.maxMatchLength) { + return null; + } + const hostParts = hostHeader.match(internals.hostHeaderRegex); if (!hostParts) { return null; @@ -100,6 +109,10 @@ exports.nowSecs = function (localtimeOffsetMsec) { }; +internals.authHeaderRegex = /^(\w+)(?:\s+(.*))?$/; // Header: scheme[ something] +internals.attributeRegex = /^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/; // !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9 + + // Parse Hawk HTTP Authorization header exports.parseAuthorizationHeader = function (header, keys) { @@ -110,7 +123,11 @@ exports.parseAuthorizationHeader = function (header, keys) { return Boom.unauthorized(null, 'Hawk'); } - const headerParts = header.match(/^(\w+)(?:\s+(.*))?$/); // Header: scheme[ something] + if (header.length > exports.limits.maxMatchLength) { + return Boom.badRequest('Header length too long'); + } + + const headerParts = header.match(internals.authHeaderRegex); if (!headerParts) { return Boom.badRequest('Invalid header syntax'); } @@ -136,9 +153,9 @@ exports.parseAuthorizationHeader = function (header, keys) { return; } - // Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9 + // Allowed attribute value characters - if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) { + if ($2.match(internals.attributeRegex) === null) { errorMessage = 'Bad attribute value: ' + $1; return; }
package.json+1 −1 modified@@ -1,7 +1,7 @@ { "name": "hawk", "description": "HTTP Hawk Authentication Scheme", - "version": "4.1.0", + "version": "4.1.1", "author": "Eran Hammer <eran@hammer.io> (http://hueniverse.com)", "repository": "git://github.com/hueniverse/hawk", "main": "lib/index.js",
test/server.js+27 −0 modified@@ -971,6 +971,33 @@ describe('Server', () => { }); }); + describe('authenticateBewit()', () => { + + it('errors on uri too long', (done) => { + + let long = '/'; + for (let i = 0; i < 5000; ++i) { + long += 'x'; + } + + const req = { + method: 'GET', + url: long, + host: 'example.com', + port: 8080, + authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"' + }; + + Hawk.server.authenticateBewit(req, credentialsFunc, {}, (err, credentials, bewit) => { + + expect(err).to.exist(); + expect(err.output.statusCode).to.equal(400); + expect(err.message).to.equal('Resource path exceeds max length'); + done(); + }); + }); + }); + describe('authenticateMessage()', () => { it('errors on invalid authorization (ts)', (done) => {
test/utils.js+28 −0 modified@@ -95,6 +95,34 @@ describe('Utils', () => { expect(host.name).to.equal('[123:123:123]'); done(); }); + + it('errors on header too long', (done) => { + + let long = ''; + for (let i = 0; i < 5000; ++i) { + long += 'x'; + } + + expect(Hawk.utils.parseHost({ headers: { host: long } })).to.be.null(); + done(); + }); + }); + + describe('parseAuthorizationHeader()', () => { + + it('errors on header too long', (done) => { + + let long = 'Scheme a="'; + for (let i = 0; i < 5000; ++i) { + long += 'x'; + } + long += '"'; + + const err = Hawk.utils.parseAuthorizationHeader(long, ['a']); + expect(err).to.be.instanceof(Error); + expect(err.message).to.equal('Header length too long'); + done(); + }); }); describe('version()', () => {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/hueniverse/hawk/commit/0833f99ba64558525995a7e21d4093da1f3e15fanvdPatchWEB
- github.com/hueniverse/hawk/issues/168nvdPatchWEB
- github.com/advisories/GHSA-jcpv-g9rr-qxrcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2016-2515ghsaADVISORY
- www.openwall.com/lists/oss-security/2016/02/20/1nvdWEB
- www.openwall.com/lists/oss-security/2016/02/20/2nvdWEB
- bugzilla.redhat.com/show_bug.cginvdWEB
- www.npmjs.com/advisories/77ghsaWEB
- nodesecurity.io/advisories/77nvd
News mentions
0No linked articles in our index yet.