Validate header names according to RFC 2616 #399

merged 1 commit into from Nov 27, 2014


None yet

5 participants


Header name validation rules are too strict. RFC 2616 allows any ASCII character, with a few exceptions. See, or:

message-header = field-name ":" [ field-value ]
field-name     = token

token          = 1*<any CHAR except CTLs or separators>
CHAR           = <any US-ASCII character (octets 0 - 127)>
separators     = "(" | ")" | "<" | ">" | "@"
                     | "," | ";" | ":" | "\" | <">
                     | "/" | "[" | "]" | "?" | "="
                     | "{" | "}" | SP | HT
CTL            = <any US-ASCII control character
                 (octets 0 - 31) and DEL (127)>
SP             = <US-ASCII SP, space (32)>
HT             = <US-ASCII HT, horizontal-tab (9)>

This commit loosens the restrictions in Rack::Lint.


This pull request fails (merged 30a8314e into edc8b92).


I don't think the fail comes from my commit, if I'm reading Travis output correctly it's

NameError: uninitialized constant Bacon::Context::Timeout
115 test/spec_utils.rb:88:in `block (2 levels) in <top (required)>': Rack::Utils - should not hang on escaping long strings that end in % (
116 test/spec_utils.rb:81:in `block in <top (required)>'
117 test/spec_utils.rb:5:in `<top (required)>'
raggi commented Aug 26, 2012

Yeah, travis seemed to be freaking out for other reasons...

@raggi raggi was assigned Aug 26, 2012


Any comment from Rack maintainers?

raggi commented Sep 4, 2012

I will take some time to look over the RFC and PR asap.

raggi commented Nov 2, 2012

So RFC 2616 only specifies rules for the field values. In section 4.2 it references RFC 822 3.2 for the field name format.

The field name format specified by 822.3.2 is as follows:

field-name  =  1*<any CHAR, excluding CTLs, SPACE, and ":">

This is much more open than even the new rule set.

raggi commented Nov 7, 2012

we must not allow '.' as it's used for rack internal names


Hey, thanks for responding.

Regarding the RFC 822 thing - RFC 2616 section 4.2 seems to reference section 3.1, not 3.2, of RFC 822. Section 3.1 just has some information about how the headers are separated from the body - nothing specific about the header format. Given RFC 2616 section 4.2 does specify header format, I think this is the correct spec to follow.

Regarding the missing '#' - I've added it.

Regarding '.' - why does the fact it's used for rack internal names mean it can't be allowed?

raggi commented Nov 9, 2012

Externally created dotted headers could cause unpredictable (read: exploitable) behavior in applications

raggi commented Dec 30, 2012

Sorry the . comment is totally invalid for this context. It only applies to incoming headers in env.

I think we've removed more than we should from the removed lines, specifically the items around newlines. Newlines are certainly not allowed in field names in HTTP.

We also should not allow :, and I'd like that to remain explicit as well.

I would say we're safe to remove the - and _ termination rules, and the last rule, and replace that with a single validation that is essentially: 1*<any CHAR, excluding CTLs, SPACE, and ":">


Ok added a new commit with following changes (once everyone is happy I can squash into a single, tidy commit):

  • re-added the check for : and \n (including the bit in spec_lint.rb)
  • updated the SPEC (this was missing from the original commit I think)

How does it look now?

raggi commented Jan 22, 2013

Nearly there, but I'd really like to get it close to the RFC and still keep Lint descriptive. I'll look into this for the next release.

@novemberborn novemberborn Validate header names according to RFC 2616
Header name validation rules are too strict. RFC 2616 allows any ASCII character save from 0-32, 127, "(", ")", "<", ">", "@", ",", ";", ":", "\", <">, "/", "[", "]", "?", "=" and "{", "}".

Cool ok well will leave it with you guys then. Just shout if you need anything from this end. Cheers.

raggi commented Jul 5, 2014

Can you check this against RFC 7320, please.

@spastorino spastorino merged commit 34b981e into rack:master Nov 27, 2014

1 check passed

default The Travis build passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment