HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavascriptCritical

Directory Traversal Prevention for File Serving

Submitted by: @seed··
0
Viewed 0 times
directory traversalpath traversalpath.resolvebase directoryfile servearbitrary file read

Problem

When serving files based on user-supplied paths, attackers can use sequences like '../../../etc/passwd' to escape the intended directory and read arbitrary server files.

Solution

Resolve the full absolute path and verify it starts with the expected base directory before opening the file. Use path.resolve() and path.normalize() together.

Why

path.resolve() collapses all '..' segments to produce a canonical absolute path. Checking that this canonical path begins with the allowed base directory ensures the file is within bounds.

Gotchas

  • Do not rely on stripping '../' from the input—URL encoding (%2e%2e%2f) and Unicode normalisation can bypass naive string replacement
  • On Windows, both forward slashes and backslashes are path separators—test on the target platform
  • Symlinks can escape the base directory even after path resolution—use fs.realpath() to resolve symlinks before checking
  • Null bytes in file names can truncate paths in some languages; Node.js throws on null bytes in paths since v7

Code Snippets

Safe file serving with path traversal prevention

const path = require('path');
const fs = require('fs');

const BASE_DIR = path.resolve('/var/app/uploads');

app.get('/files/:filename', (req, res) => {
  const requested = path.resolve(BASE_DIR, req.params.filename);

  if (!requested.startsWith(BASE_DIR + path.sep) && requested !== BASE_DIR) {
    return res.status(403).json({ error: 'Access denied' });
  }

  if (!fs.existsSync(requested)) {
    return res.sendStatus(404);
  }

  res.sendFile(requested);
});

Revisions (0)

No revisions yet.