HIGH path traversalexpressapi keys

Path Traversal in Express with Api Keys

Path Traversal in Express with Api Keys — how this specific combination creates or exposes the vulnerability

Path Traversal in an Express API protected only by API keys remains a classic web vulnerability despite the presence of authentication. An API key proves identity or subscription status, but it does not enforce authorization on filesystem operations. If an endpoint accepts user input—often a filename or path parameter—and uses it directly with Node.js utilities such as fs.readFile or path.join, an attacker can supply sequences like ../../../etc/passwd to traverse directory boundaries and read files outside the intended directory.

Consider an Express route that serves configuration files based on a keyed request without validating or sanitizing the path:

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

const app = express();

app.get('/config', (req, res) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || apiKey !== process.env.VALID_API_KEY) {
    return res.status(401).send('Unauthorized');
  }

  const filename = req.query.name;
  const filePath = path.join('/opt/app/configs', filename);
  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) return res.status(404).send('Not found');
    res.send(data);
  });
});

app.listen(3000);

Here, the API key check passes, but the filename query parameter is used unsafely. An attacker can send ?name=../../../etc/passwd and, because the path is joined without canonicalization or strict allowlisting, the server may leak sensitive system files. This demonstrates that API keys protect access to the endpoint, not the correctness of the operation; Path Traversal persists because the application trusts user input for filesystem navigation.

In a black-box scan, middleBrick tests such endpoints by submitting traversal sequences and checking whether responses differ from expected behavior, indicating unauthorized file exposure. Even when API keys are required, findings may surface if the scanner can reach the endpoint with a valid key or if the key is inadvertently omitted in tests. The presence of an API key does not eliminate the risk; it only changes the attacker’s prerequisites.

Api Keys-Specific Remediation in Express — concrete code fixes

To remediate Path Traversal while using API keys in Express, you must treat API keys as identity proof and still enforce strict path controls. Do not rely on the key alone to prevent unsafe filesystem access. Apply defense in depth: validate and sanitize input, use allowlisting, and avoid direct filesystem paths derived from user data.

1. Use a strict allowlist of permitted filenames

Instead of constructing paths from raw input, map allowed logical names to real filenames:

const allowed = new Set(['app.yml', 'service.json', 'routes.yaml']);

app.get('/config', (req, res) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || apiKey !== process.env.VALID_API_KEY) {
    return res.status(401).send('Unauthorized');
  }

  const name = req.query.name;
  if (!allowed.has(name)) {
    return res.status(400).send('Invalid config name');
  }

  const filePath = path.join('/opt/app/configs', name);
  fs.readFile(filePath, 'utf8', (err, data) => {
    if (err) return res.status(404).send('Not found');
    res.send(data);
  });
});

2. Normalize and validate paths with path.resolve and a chroot-like base check

Resolve the final path and ensure it remains under the intended base directory:

app.get('/files', (req, res) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || apiKey !== process.env.VALID_API_KEY) {
    return res.status(401).send('Unauthorized');
  }

  const requested = path.resolve(req.query.file || '');
  const base = path.resolve('/opt/app/uploads');

  if (!requested.startsWith(base)) {
    return res.status(403).send('Forbidden path');
  }

  fs.readFile(requested, 'utf8', (err, data) => {
    if (err) return res.status(404).send('Not found');
    res.send(data);
  });
});

3. Use a hardened path library for complex routing

For more dynamic needs, consider a library approach that enforces canonical paths and prevents null-byte and encoding tricks:

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

const app = express();
const safeJoin = (base, target) => {
  const targetResolved = path.resolve(target);
  const baseResolved = path.resolve(base);
  return targetResolved.startsWith(baseResolved) ? targetResolved : null;
};

app.get('/docs', (req, res) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || apiKey !== process.env.VALID_API_KEY) {
    return res.status(401).send('Unauthorized');
  }

  const safePath = safeJoin('/opt/app/public', req.query.path);
  if (!safePath) return res.status(403).send('Invalid path');

  fs.readFile(safePath, 'utf8', (err, data) => {
    if (err) return res.status(404).send('Not found');
    res.send(data);
  });
});

These patterns ensure that even when API keys are valid, the application does not allow directory escapes. Combine this with runtime scans using middleBrick to detect Path Traversal and verify that your remediation behaves as expected under unauthenticated attack surface testing.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does requiring an API key prevent Path Traversal in Express?
No. API keys authenticate or authorize access to an endpoint but do not validate user input. If a route uses unchecked user-controlled paths for filesystem operations, traversal attacks remain possible regardless of key presence.
Should I use middleware to strip ‘..’ segments to prevent Path Traversal?
Relying solely on stripping sequences like ‘..’ is insufficient due to encoding and double-encoding bypasses. Use allowlisting, path resolution, and base-directory checks to robustly prevent traversal.