How can I securely build paths from url segments?

I have the following code:

app.get('/games/:id/log', function (req, res) {
    fs.readFile('logs/' + req.params.id +'.log', 'utf8', function (err, data) {
        res.send(data.split('\n').join('\<br />'));
    });
});

Which allows accessing mysite.com/games/somename/log to serve up ./logs/somename.log. However, I'm worried that req.params.id could end up being something evil like ../.., reading files that I don't want to be visible.

Is this possible? If so, how can I fix this security problem?

I would create a white list of characters you would allow in your id. My guess is that your id can only be alpha characters. So running a test would allow you to reject all other values.

var id = req.params.id.match(/[A-Z]+/i
    id = id[0] || null

if (id) {
  // read file `id`
}

This will clean your input only allowing upper and lower case alpha characters. You could also test the input for a valid characters instead of just cleaning it.

var reg = /^[A-Z]+$/i


if (reg.test(req.params.id)) {
  // read file `req.params.id`
}

Also note: You will never be able to get ../.. as a value for id, as it would not match your routing.

You can see more info about the routing via req.route

Example of your route would be:

{ path: '/games/:id/log',
  method: 'get',
  callbacks: [ [Function] ],
  keys: [ { name: 'id', optional: false } ],
  regexp: /^\/games\/(?:([^\/]+?))\/log\/?$/i,
  params: [ id: 'asd' ] } [ id: 'asd' ]
}

http://expressjs.com/api.html#req.route