# Bug: invalid HTTP responses on invalid data

**URL:** <https://www.ruby-forum.com/t/bug-invalid-http-responses-on-invalid-data/185278>\
**Category:** NGINX\
**Created:** [March 17, 2010, 12:04pm UTC](https://www.ruby-forum.com/t/bug-invalid-http-responses-on-invalid-data/185278 "2010-03-17T12:04:33Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![david\_lodge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/5f9b8f/32.png) [@david\_lodge](https://www.ruby-forum.com/u/david_lodge)\
**Post date:** [March 17, 2010, 12:04pm UTC](https://www.ruby-forum.com/t/bug-invalid-http-responses-on-invalid-data/185278/1 "2010-03-17T12:04:33Z")

</div>

Nginx seems to offer some strange behaviour when it receives invalid  
tokens in the HTTP request. If an unexpected character is sent then  
the stream will immediately terminate, returning an HTML page for the  
400 error. More importantly, this response does not contain a valid  
HTTP 400 code.

For example if I send a request with a lower case “get” method, I’d  
expect the webserver to return an HTTP 400 message, but with nginx we  
find:

D:\tools\netcat\>echo “a” | nc 127.0.0.1 80

400 Bad Request
# 400 Bad Request

* * *
nginx/0.7.65

Similarly with an OPTIONS \* HTTP/1.1 request (which is a valid HTTP  
request - as it should return options valid to the server, not to a  
URI):  
D:\tools\netcat\>echo “OPTIONS \* HTTP/1.1” | nc 127.0.0.1 80

400 Bad Request
# 400 Bad Request

* * *
nginx/0.7.65

I can understand why the stream is immediately terminated, that it  
minimises risk of out of band data. But the response should include a  
valid HTTP code and be conformant to the RFC, just like a request for  
TEST / HTTP/1.1 does:  
HTTP/1.1 400 Bad Request  
Server: nginx/0.7.65  
Date: Wed, 17 Mar 2010 11:03:27 GMT  
Content-Type: text/html  
Content-Length: 173  
Connection: close

400 Bad Request
# 400 Bad Request

* * *
nginx/0.7.65

---

<div class="post-metadata">

**Author:** ![david\_lodge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/5f9b8f/32.png) [@david\_lodge](https://www.ruby-forum.com/u/david_lodge)\
**Post date:** [March 17, 2010, 1:10pm UTC](https://www.ruby-forum.com/t/bug-invalid-http-responses-on-invalid-data/185278/2 "2010-03-17T13:10:41Z")

</div>

Hello!

On Wed, Mar 17, 2010 at 11:03:59AM +0000, david lodge wrote:

> D:\tools\netcat\>echo “a” | nc 127.0.0.1 80
> 
> 400 Bad Request
> # 400 Bad Request
> 
> * * *
> nginx/0.7.65

This is perfectly valid HTTP/0.9 response to invalid HTTP/0.9  
request. No problem here.

> 

This seems to be bug indeed. nginx doesn’t support OPTIONS, and  
doesn’t correctly recognize this as HTTP/1.1 request as it  
contains ‘\*’ (which is only allowed in OPTIONS).

The same will happen for CONNECT method with authority specified.

Probably these two should be recognized and return 501.

Maxim D.

---

<div class="post-metadata">

**Author:** ![david\_lodge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/5f9b8f/32.png) [@david\_lodge](https://www.ruby-forum.com/u/david_lodge)\
**Post date:** [March 17, 2010, 1:14pm UTC](https://www.ruby-forum.com/t/bug-invalid-http-responses-on-invalid-data/185278/3 "2010-03-17T13:14:12Z")

</div>

At Wed, 17 Mar 2010 15:10:03 +0300,  
Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> This is perfectly valid HTTP/0.9 response to invalid HTTP/0.9  
> request. No problem here.

Why not take requests on default 1.0+?

–  
wbr, Kirill

---

<div class="post-metadata">

**Author:** ![david\_lodge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/5f9b8f/32.png) [@david\_lodge](https://www.ruby-forum.com/u/david_lodge)\
**Post date:** [March 17, 2010, 1:44pm UTC](https://www.ruby-forum.com/t/bug-invalid-http-responses-on-invalid-data/185278/4 "2010-03-17T13:44:04Z")

</div>

> > Nginx seems to offer some strange behaviour when it receives invalid  
> > tokens in the HTTP request. If an unexpected character is sent then  
> > the stream will immediately terminate, returning an HTML page for the  
> > 400 error. More importantly, this response does not contain a valid  
> > HTTP 400 code.  
> > D:\tools\netcat\>echo “a” | nc 127.0.0.1 80
> 
> This is perfectly valid HTTP/0.9 response to invalid HTTP/0.9  
> request. No problem here.

That’d make sense, though looking at RFC1945 it does seem that it  
should only return a HTTP/0.9 response if a simple-request is sent:

Simple-Request = “GET” SP Request-URI CRLF

Which is sort of messed up as it terminates the stream as soon as it  
reads an out-of-bands character, so even if I send “get / HTTP/1.1”  
I’ll still get the HTTP/0.9 message (as the connection will terminate  
of the “g”).

(Of course it is feasible, though unlikely, that an HTTP method could  
be called “get” which wouldn’t be the same as “GET”.)

> > Similarly with an OPTIONS \* HTTP/1.1 request (which is a valid HTTP  
> > request - as it should return options valid to the server, not to a  
> > URI):  
> > D:\tools\netcat\>echo “OPTIONS \* HTTP/1.1” | nc 127.0.0.1 80  
> > This seems to be bug indeed. nginx doesn’t support OPTIONS, and  
> > doesn’t correctly recognize this as HTTP/1.1 request as it  
> > contains ‘\*’ (which is only allowed in OPTIONS).

The problem being that as soon as nginx sees an "_" in the URI  
location it will terminate the stream, e.g. if you give a URI of  
 [http://127.0.0.1/fred?jim=](http://127.0.0.1/fred?jim=)_

The RFCs are contradictory on this - 1945 (HTTP/1.0 and 0/9) says that

- is valid in a URI; 2616 (HTTP/1.1) says that \* is a special case  
that refers to the server, not to a specific resource.

> Probably these two should be recognized and return 501.

Would 405 (method not allowed) be better for an unknown method than  
501 (not implemented)?

This is _not_ a serious issue and I only found it because I’m testing  
edge cases on web servers. Most normal use wouldn’t even see this  
behaviour (though it is possible for a badly implemented agent to send  
a \* as a cgi parameter, in which case it could become prominent).

dave

---

<div class="post-metadata">

**Author:** ![david\_lodge](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/5f9b8f/32.png) [@david\_lodge](https://www.ruby-forum.com/u/david_lodge)\
**Post date:** [March 17, 2010, 1:32pm UTC](https://www.ruby-forum.com/t/bug-invalid-http-responses-on-invalid-data/185278/5 "2010-03-17T13:32:21Z")

</div>

Hello!

On Wed, Mar 17, 2010 at 03:13:44PM +0300, Kirill A. Korinskiy wrote:

> At Wed, 17 Mar 2010 15:10:03 +0300,  
> Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > This is perfectly valid HTTP/0.9 response to invalid HTTP/0.9  
> > request. No problem here.
> 
> Why not take requests on default 1.0+?

RFC 1945 explicitly says:

The version of an HTTP message is indicated by an HTTP-Version field  
in the first line of the message. If the protocol version is not  
specified, the recipient must assume that the message is in the  
simple HTTP/0.9 format.

This basically means that HTTP/1.0 support requires this  
behaviour.

Maxim D.
