Information Disclosure in Express
How Information Disclosure Manifests in Express
Information disclosure in Express applications often occurs through misconfigured error handling, verbose logging, and default behaviors that leak sensitive data. One of the most common patterns is Express's default error handling middleware, which can inadvertently expose stack traces and internal implementation details to clients.
Consider this vulnerable pattern:
app.get('/api/users/:id', (req, res) => {
const userId = req.params.id;
const user = db.getUser(userId); // Assume this throws an error
res.json(user);
});When db.getUser() throws an error, Express's default error handler sends the stack trace to the client:
{
"message": "Cannot read property 'email' of undefined",
"stack": "TypeError: Cannot read property 'email' of undefined\n at db.getUser (/app/models/user.js:42:15)\n at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)\n ..."
}This stack trace reveals your file structure, line numbers, and internal dependencies—valuable information for attackers.
Another Express-specific disclosure vector is the X-Powered-By header. By default, Express includes:
X-Powered-By: ExpressThis immediately identifies your server as an Express application, allowing attackers to target Express-specific vulnerabilities.
Environment variable exposure is another critical issue. Many Express apps accidentally expose configuration through error messages or logging:
app.use(express.json());
app.post('/webhook', (req, res) => {
const secret = process.env.WEBHOOK_SECRET;
if (req.body.secret !== secret) {
throw new Error('Invalid webhook secret: ' + secret); // DON'T DO THIS
}
});Express's error handling will include the actual secret value in the response, completely compromising your webhook security.
Directory traversal vulnerabilities can also lead to information disclosure. Express's res.sendFile() and static middleware can be misconfigured:
app.use(express.static('public')); // Serves entire directory structure
app.get('/download/:filename', (req, res) => {
res.sendFile(req.params.filename, { root: __dirname }); // Path traversal risk
});An attacker can request /download/../../package.json to read your application's dependencies and potentially sensitive configuration.
Finally, verbose logging middleware can log sensitive request data:
app.use(morgan(':method :url :status :response-time :body')); // Logs request bodies
This logs POST request bodies, potentially including passwords, API keys, or personal data to your logs.
Express-Specific Detection
Detecting information disclosure in Express applications requires both manual code review and automated scanning. middleBrick's black-box scanning approach is particularly effective for Express applications because it tests the actual runtime behavior without requiring source code access.
When middleBrick scans an Express endpoint, it checks for several Express-specific disclosure patterns:
Stack Trace Exposure: middleBrick intentionally triggers errors by sending malformed requests, then analyzes the responses for stack traces, file paths, and internal error details. It looks for patterns like:
"stack": "Error: ...\n at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)"Default Headers: The scanner checks for X-Powered-By: Express headers and other identifying information that reveals your technology stack.
Verbose Error Messages: middleBrick tests error conditions and analyzes whether sensitive data (database queries, environment variables, internal IDs) is exposed in error responses.
Directory Traversal: The scanner attempts path traversal attacks like /download/../../package.json and /static/../../../etc/passwd to test if Express's static middleware is properly configured.
Environment Variable Leakage: By triggering specific error conditions, middleBrick can detect if environment variables or configuration data are accidentally exposed in responses.
For development teams, the middleBrick CLI provides a quick way to scan Express APIs:
npm install -g middlebrick
middlebrick scan https://api.example.com/users/123The CLI returns a security score with specific findings about information disclosure, including severity levels and remediation guidance.
GitHub Action integration allows continuous monitoring of Express API security:
- name: Scan API Security
uses: middlebrick/middlebrick-action@v1
with:
url: https://api.example.com
fail_below: B
token: ${{ secrets.MIDDLEBRICK_TOKEN }}This automatically scans your Express API endpoints on every pull request, failing the build if information disclosure vulnerabilities are detected.
The middleBrick MCP Server enables scanning directly from AI coding assistants like Claude or Cursor:
npm install -g @middlebrick/mcp-server
middlebrick scan https://api.example.comThis allows developers to scan Express endpoints while coding, getting immediate feedback about potential information disclosure issues.
Express-Specific Remediation
Remediating information disclosure in Express requires a combination of configuration changes, custom error handling, and security middleware. Here's how to address each vulnerability type:
Custom Error Handling: Replace Express's default error handler with a custom implementation that never exposes stack traces to clients:
app.use((err, req, res, next) => {
console.error(err); // Log the full error internally
if (err instanceof ValidationError) {
return res.status(400).json({
error: 'Invalid request data',
details: err.details // Generic error details only
});
}
return res.status(500).json({
error: 'Internal server error',
message: 'An unexpected error occurred'
});
});Remove X-Powered-By Header: Disable Express's identifying header:
app.disable('x-powered-by');Secure Static File Serving: Configure Express's static middleware with proper options:
app.use(express.static('public', {
dotfiles: 'ignore',
index: false,
redirect: false
}));Input Validation and Sanitization: Use validation middleware to prevent path traversal:
const express = require('express');
const path = require('path');
const app = express();
app.use(express.json());
// Safe file download handler
app.get('/download/:filename', (req, res, next) => {
const safeFilename = path.basename(req.params.filename);
const filePath = path.join(__dirname, 'uploads', safeFilename);
// Verify file exists and is within allowed directory
if (!filePath.startsWith(path.join(__dirname, 'uploads'))) {
return res.status(400).json({ error: 'Invalid file request' });
}
res.sendFile(filePath, (err) => {
if (err) {
console.error('File send error:', err);
return res.status(404).json({ error: 'File not found' });
}
});
});Secure Logging: Configure logging middleware to exclude sensitive data:
const morgan = require('morgan');
// Custom token that excludes request bodies
morgan.token('body', (req) => 'REDACTED');
app.use(morgan(':method :url :status :response-time')); // No body loggingEnvironment Variable Security: Never expose environment variables in error messages:
app.post('/webhook', (req, res) => {
const secret = process.env.WEBHOOK_SECRET;
if (!secret) {
console.error('Missing webhook secret');
return res.status(500).json({ error: 'Webhook configuration error' });
}
if (req.body.secret !== secret) {
return res.status(401).json({ error: 'Invalid webhook signature' });
}
});Security Headers: Add security headers to prevent information disclosure:
const helmet = require('helmet');
app.use(helmet({
hidePoweredBy: { setTo: 'PHP 4.2.0' } // Obfuscate instead of revealing Express
}));Development vs Production Configuration: Use different error handling based on environment:
if (process.env.NODE_ENV === 'production') {
// Production: minimal error details
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({ error: 'Internal server error' });
});
} else {
// Development: detailed errors for debugging
app.use((err, req, res, next) => {
res.status(500).json({
error: err.message,
stack: err.stack
});
});
}These remediation techniques, combined with regular middleBrick scanning, create a robust defense against information disclosure in Express applications.