Request timeout if a single header exceeds the max-http-header-size limit

  • Version: 10.15.1
  • Platform: 18.2.0 Darwin Kernel Version 18.2.0: Thu Dec 20 20:46:53 PST 2018; root:xnu-4903.241.1~1/RELEASE_X86_64 x86_64
  • Subsystem: http

If a request header exceeds the max-http-header-size in Node 10.15.1 and 10.15.0 the request hangs leaving the socket open until the server times out. This seems like it could be a potential DoS attack vector. On Node 10.14.1 a 400 response is received as expected. The code below demonstrates the issue. If you run the code on 10.14.1 both requests will return immediately with a 400 as expected. On 10.15.1 the second request times out.

You can grab the test script from here also. https://github.com/natedanner/node-max-header-timeout/blob/master/server.js

const http = require('http');
const port = 3000;

const server = http.createServer((req, res) => {
	res.writeHead(200, {'Content-Type': 'text/plain; charset=UTF-8'});
	res.end('Hello World\n');
})

server.listen(port, () => {
	console.log(`Listening on ${port}`);

	// Headers that together exceed default 8k limit
	const defaultHeaders = {
		'FOO': '6'.repeat(8100),
		'BAR': '6'.repeat(8192)
	};
	
	function callServer(callerName, headers) {
		return http.get('http://localhost:3000', { headers }, (response) => {
			console.log(callerName, 'responded with:', response.statusCode);
		});
	}
	
	const excessHeadersRequest = callServer('EXCESS_HEADER', defaultHeaders);
	excessHeadersRequest.setTimeout(2000, () => {
		console.log('SHOULD NOT SEE THIS');
	});

	// If you exceed header limit on a single header by 1 then the request hangs open
	defaultHeaders['BAR'] += '6'
	const headerTimeoutRequest = callServer('EXCESS_HEADER_TIMEOUT', defaultHeaders);
	headerTimeoutRequest.setTimeout(2000, () => {
		console.log('EXCESS_HEADER_TIMEOUT CALL TIMED OUT!');
	});
});