Path Traversal in Express with Bearer Tokens
Path Traversal in Express with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Path Traversal in Express when Bearer Tokens are used for authorization can arise when access control relies only on the presence and validity of a token, without properly constraining file-system paths that the endpoint resolves. A common pattern is an unauthenticated or under-constrained route that builds a filesystem path from request parameters (e.g., req.params.file) and serves it after verifying a Bearer token. If the token is treated as a sufficient authorization boundary, an attacker who obtains or guesses a valid token can exploit path manipulation (e.g., ../../../etc/passwd) to read arbitrary files, assuming the server does not normalize and validate the resulting path.
Consider an Express endpoint that uses a Bearer Token to gate access to file downloads but constructs the path directly from user input:
const express = require('express');
const fs = require('fs');
const app = express();
app.get('/files/:name', (req, res) => {
const token = req.headers.authorization?.split(' ')[1];
if (!validateBearer(token)) return res.status(401).send('Unauthorized');
const file = `./uploads/${req.params.name}`;
fs.readFile(file, (err, data) => {
if (err) return res.status(404).send('Not found');
res.send(data);
});
});
In this setup, a valid Bearer Token bypasses authentication checks, but the route remains vulnerable to traversal if req.params.name is not strictly validated. An attacker can supply ?name=../../../etc/passwd and, with a valid token, read sensitive files. The risk is not that tokens are weak, but that authorization is incomplete: the token proves identity, not authorization for a specific file path. This becomes more significant when tokens are leaked or shared, or when endpoints expose directory traversal functionality inadvertently.
Another scenario involves serving user-uploaded content where filenames are stored in a database and retrieved via an ID that is mapped to a path. If the mapping is not canonicalized, an attacker who obtains a valid token (via phishing or token leakage) can traverse outside the intended directory by manipulating the ID or related query parameters. The Bearer Token in this context acts as a gatekeeper but does not prevent path manipulation once the gate is passed.
middleBrick’s LLM/AI Security checks are relevant here because prompt injection or system prompt leakage tests can uncover whether API documentation or error messages inadvertently expose path-handling logic or reveal directory structures when tokens are used. These checks complement the 12 security scans, including Input Validation and Authentication, which together help identify whether path traversal vectors exist alongside authorization mechanisms like Bearer Tokens.
Bearer Tokens-Specific Remediation in Express — concrete code fixes
To secure Express routes that use Bearer Tokens, combine strict path validation with a robust authorization model that treats tokens as identity, not as authorization for arbitrary paths. Below are concrete, safe patterns.
1. Validate and sanitize paths
Always resolve paths against a strict allowlist or a base directory, and use path.resolve() and path.relative() to ensure the final path remains within the intended directory.
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const UPLOAD_DIR = path.resolve(__dirname, 'uploads');
app.get('/files/:name', (req, res) => {
const token = req.headers.authorization?.split(' ')[1];
if (!validateBearer(token)) return res.status(401).send('Unauthorized');
const rawName = req.params.name;
const safeName = path.normalize(rawName).replace(/^(\.\.[/\\])+/, '');
const filePath = path.resolve(UPLOAD_DIR, safeName);
if (!filePath.startsWith(UPLOAD_DIR)) {
return res.status(403).send('Forbidden');
}
fs.readFile(filePath, (err, data) => {
if (err) return res.status(404).send('Not found');
res.send(data);
});
});
This ensures that even if rawName contains ../../../etc/passwd, the resolved path will be confined to UPLOAD_DIR.
2. Use route-based authorization with user-scoped checks
Instead of relying on the token alone, associate the token with allowed paths or resources. For example, decode the token (if it contains user or resource metadata) and verify ownership or permissions before serving the file.
app.get('/files/:name', async (req, res) => {
const token = req.headers.authorization?.split(' ')[1];
const user = validateBearer(token); // returns user object or null
if (!user) return res.status(401).send('Unauthorized');
const fileRecord = await db.files.findOne({ name: req.params.name });
if (!fileRecord || fileRecord.userId !== user.id) {
return res.status(403).send('Forbidden');
}
const filePath = path.join(UPLOAD_DIR, fileRecord.safeName);
fs.readFile(filePath, (err, data) => {
if (err) return res.status(404).send('Not found');
res.send(data);
});
});
This approach treats the Bearer Token as an authentication mechanism and adds explicit authorization per resource, preventing traversal by ensuring the user can only access files they own.
3. Prefer serving files via a controller rather than direct filesystem reads
Stream files through Express without exposing filesystem paths to the client. Use res.sendFile with an absolute path after validation:
app.get('/files/:name', (req, res) => {
const token = req.headers.authorization?.split(' ')[1];
if (!validateBearer(token)) return res.status(401).send('Unauthorized');
const safeName = path.basename(req.params.name);
const filePath = path.join(UPLOAD_DIR, safeName);
res.sendFile(filePath, (err) => {
if (err) res.status(404).send('Not found');
});
});
path.basename strips directory segments, but combining it with a base directory and explicit checks provides defense in depth.
Using the middleBrick CLI (middlebrick scan <url>) or GitHub Action can help detect such path traversal issues in your API endpoints by correlating authentication mechanisms with input validation findings. The dashboard can track these scans over time, and the MCP Server allows you to run checks directly from your AI coding assistant while developing.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |
Frequently Asked Questions
Does using Bearer Tokens alone prevent path traversal in Express APIs?
How can I test if my Express endpoints are vulnerable to path traversal when using Bearer Tokens?
middlebrick scan <url>) or GitHub Action to scan your API. These tools test input validation and authentication checks, including scenarios where valid tokens are paired with manipulated paths.