Express: TypeError: res.set is not a function

Created on 13 Jul 2016  路  10Comments  路  Source: expressjs/express

My server is scanned by the security team of my company to detect secutity flaws, and I've got a strange error in my console:

Here is the logged stack:

GET /mainui/ 404 2.194 ms - 9
TypeError: res.set is not a function
at sendOptionsResponse (c:\git\WebSite\node_modules\express\lib\router\index.js:626:9)
at c:\git\WebSite\node_modules\express\lib\router\index.js:168:7
at proxy (c:\git\WebSite\node_modules\express\lib\router\index.js:643:8)
at next (c:\git\WebSite\node_modules\express\lib\router\index.js:256:14)
at trim_prefix (c:\git\WebSite\node_modules\express\lib\router\index.js:286:45)
at c:\git\WebSite\node_modules\express\lib\router\index.js:280:7
at Function.process_params (c:\git\WebSite\node_modules\express\lib\router\index.js:330:12)
at next (c:\git\WebSite\node_modules\express\lib\router\index.js:271:10)
at trim_prefix (c:\git\WebSite\node_modules\express\lib\router\index.js:286:45)
at c:\git\WebSite\node_modules\express\lib\router\index.js:280:7
GET / 200 2.574 ms - 21440

I'm using express 4.14.0

Is it normal that such a function is not defined?

Code around line 626 is:

// send an OPTIONS response
function sendOptionsResponse(res, options, next) {
  try {
    var body = options.join(',');
    res.set('Allow', body);
    res.send(body);
  } catch (err) {
    next(err);
  }
}
4.x bug

Most helpful comment

The request OPTIONS * HTTP/1.1 is a valid HTTP request; the middle section is allowed to be a single * in the HTTP specification. I am able to reproduce the issue. We'll get it fixed up in 4.14.1 :)

All 10 comments

Can you provide more context or a sample reproduction? Are you sure that it's a response argument in the first position?

I cannot provide a sample reproduction, for I don't know what the IDS/IPS is sending to my site.
So I will add a console.log( res ) in index.js and wait for the next request to trigger this function call.

(Or maybe you may want I run node with special parameters (I don't know how) that will log function agument values?)

I added the line console.log( "ISSUE-337", res, options, next ); line 628 then I got the following log when my server was scanned again:

issue-337.txt

I don't know if it could help... Maybe you need the req?

@noopole can you share the details of the request which results in res.set being undefined? I can't think of a scenario when res.set would be undefined.

@noopole Thanks for the link. It's definitely the response object, but it looks like a raw node.js response object and not one wrapped by Express.js. Is it possible where you're using this is using raw req/res objects and not Express?

@hacksparrow ok I will log req too and send you the log at next IDS scan (maybe tomorrow).
@blakeembrey I don't know, so I attached my full (simple) sever.js file.
server.zip

It's either the _static_ or app.get( '*' ... ) which is inkoked I guess. Maybe my code doesn't like OPTIONS + HEAD requests.

EDIT 21/7/2016 Sorry for the confusion: I wrote OPTIONS + HEAD but actually I was meaning GET + HEAD, the options parameters of the failing function.

Thanks. I can't seem to replicate it locally or see how the script could cause you issues. Have you found a way to replicate it yourself. Here's some logs from my testing:

OPTIONS /npp 200 6.063 ms - 8
OPTIONS / 200 0.907 ms - 8
OPTIONS /mainui/ 200 0.444 ms - 8
::1
GET /mainui/ 404 2.914 ms - 9
::1
GET / 404 1.041 ms - 9

Is there something else in your script because looking at your logs you have a 21440 byte successful response for /?

I cannot replicate it myself so I will log the req content line 168 of lib/router/index.js before.

The successful 21440 bytes GET is the index.html file in my public folder. The /mainui/ GET request is one of the hundred more or less malformed requests that the IDS/IPD send my server in order to compromise it.

If the issue occurs again today I will open a ticket to my IT helpdesk to ask for the details of the attack (with no hope, it's a big, worldwide company...).

Last option, I could install a sniffer on my server to catch all the received requests but I'm not a network specialist.

It seems that the HTTP request that makes it happen starts like this:
OPTIONS * HTTP/1.1
I think it's not a well-formed URL, so I don't know how to reproduce it.

Attached is the log for REQ and RES:
issue-337-req.txt

The request OPTIONS * HTTP/1.1 is a valid HTTP request; the middle section is allowed to be a single * in the HTTP specification. I am able to reproduce the issue. We'll get it fixed up in 4.14.1 :)

Was this page helpful?
0 / 5 - 0 ratings