Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

http: sanitize http headers and method names #13

Closed
@jasnell

Description

@jasnell

Simple test case:

var http = require('http');
var server = http.createServer(function(req, res) {
    res.setHeader('Foo\n\nBar', 'Value');
    res.end();
});
server.listen(3000, function() {
  console.log('server started');
});

Then do a curl -v http://localhost:3000

This is not a new issue (nodejs/node-v0.x-archive#2602, nodejs/node-v0.x-archive#9076). It affects HTTP request methods and header names. It happens in v0.10, v0.12, and current io.js:

var http = require('http');
var server = http.createServer(function(req,res) {
  res.writeHead(200, {'Foo\n\nBar': 'Value'});
  res.end('okay');
});
server.listen(3000, function() { console.log('started'); });

I have the code written up to perform the necessary fix but I need a decision: when an invalid http method or header name is passed in, should we throw or attempt to sanitize? Throwing is a API change that breaks backwards compatibility but this is an obvious error with potential security ramifications (fairly low risk). Sanitizing can lead to unexpected results and there is no standard pattern we can follow. Throwing seems to be the best approach.

// http token is defined in RFC2616 as...
//   token          = 1*<any CHAR except CTLs or separators>
//   separators     = "(" | ")" | "<" | ">" | "@"
//                  | "," | ";" | ":" | "\" | <">
//                  | "/" | "[" | "]" | "?" | "="
//                  | "{" | "}" | SP | HT
// and redefined in RFC7230 as ...
//   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
//     "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
//   token = 1*tchar
//
// This checks the input to make sure it's valid according to the
// http token rule. If the input doesn't match, it throws, if it
// does match, val is returned.
function checkIsHttpToken(val, label) {
  if (!val || typeof val !== 'string')
    return false;
  for (var n = 0, l = val.length; n < l; n++) {
    var c = val.charCodeAt(n);
    if (c <= 32 || c == 34 ||
        c == 44 || c == 47 ||
        c == 123 || c == 125 ||
        c == 40 || c == 41 ||
        (c >= 58 && c <= 64) ||
        (c >= 91 && c <= 93) ||
        c >= 128)
      throw new Error(
          'Invalid character (' +
          String.fromCharCode(c) +
          ') in HTTP ' + label + ' at position ' + (n + 1));
  }
  return val;
}

@nodejs/tsc ... thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions