senchalabs/connect — Issue #452: Static middleware crashes node server when URL contains a trailing backslash
Author: bunkat
Created: 2012-01-07 17:41:33+00:00
State: open

When using the static middleware, if the URL contains a valid file name and a trailing backslash the node server will crash with `Error: ENOENT, no such file or directory`.

Example server code:

```javascript
var express = require('express');
var app = express.createServer();

// Configuration
app.configure(function() {
app.use(express.static(__dirname + '/public'));
});

// 404
app.get('*', function(req, res) {
res.send('not found', 404);
});

app.listen(3000);
```

Place a file called `index.html` in the `/public` directory and visit `localhost:3000/index.html\` (note the trailing backslash). The node server will crash instead of being handled by the 404 route as expected. Since the node server crashes, this is a pretty easy denial of service attack.

The reason for this behavior (as pointed out by Felix Loether on stackoverflow) seems to be the difference in how `fs.stat` and `fs.createReadStream` handle trailing backslashes.

When the string 'path/to/public/index.html\\' is given to fs.stat in the static middleware, it is ignored (running `stat index.html\` on the command line checks for a file named index.html, you'd have to run `stat index.html\\` for index.html\). So `fs.stat` thinks the file was found because it thinks you're asking for index.html, and doesn't call the next middleware handler.

Later, that string is passed to `fs.createReadStream` which thinks it's looking for index.html\. It doesn't find that file and throws said error.

To get around this issue, I used a simple custom middleware to strip out trailing backslashes from the request.

```javascript
app.use(function(req, res, next) {
req.url = req.url.replace(/(%5C)+$/, "");
next();
});
```