Sensitive Data Exposure Through Verbose API Error Messages

Medium Risk API Security
apiinformation-disclosureerror-handlingreconnaissancedata-exposurestack-traces

What it is

A medium-severity vulnerability where APIs return overly detailed error messages that expose sensitive information about the system architecture, database structure, file paths, internal configurations, or user data. These verbose error messages can provide attackers with valuable reconnaissance information to plan targeted attacks, understand system internals, and identify potential attack vectors.

// VULNERABLE: Exposing database errors const express = require('express'); const mysql = require('mysql2'); const app = express(); // VULNERABLE: Database error exposure app.get('/api/users/:id', (req, res) => { const query = `SELECT * FROM users WHERE id = ?`; db.execute(query, [req.params.id], (error, results) => { if (error) { // VULNERABLE: Exposing database details return res.status(500).json({ error: 'Database query failed', details: error.message, code: error.code, sqlMessage: error.sqlMessage, query: query }); } if (results.length === 0) { // VULNERABLE: Reveals schema return res.status(404).json({ error: 'User not found', searchedId: req.params.id, table: 'users', query: query }); } res.json(results[0]); }); }); // VULNERABLE: File system error exposure app.post('/api/upload', (req, res) => { fs.writeFile('/uploads/' + req.body.filename, req.body.data, (err) => { if (err) { // VULNERABLE: Exposes file paths return res.status(500).json({ error: 'File write failed', path: err.path, syscall: err.syscall, stack: err.stack }); } res.json({ success: true }); }); });
// SECURE: Generic error messages const express = require('express'); const mysql = require('mysql2'); const logger = require('./logger'); const app = express(); // SECURE: Centralized error handler const handleError = (error, res) => { // Log detailed error server-side logger.error({ message: error.message, stack: error.stack, code: error.code }); // Return generic message to client res.status(500).json({ error: 'An error occurred', requestId: generateRequestId() }); }; app.get('/api/users/:id', (req, res) => { const query = `SELECT * FROM users WHERE id = ?`; db.execute(query, [req.params.id], (error, results) => { if (error) { // SECURE: Generic error, details logged return handleError(error, res); } if (results.length === 0) { // SECURE: No schema details exposed return res.status(404).json({ error: 'Resource not found' }); } res.json(results[0]); }); }); app.post('/api/upload', (req, res) => { fs.writeFile('/uploads/' + sanitizeFilename(req.body.filename), req.body.data, (err) => { if (err) { // SECURE: No paths or stack traces return res.status(500).json({ error: 'Upload failed', requestId: generateRequestId() }); } res.json({ success: true }); }); });

💡 Why This Fix Works

The vulnerable code exposes sensitive information through error messages including database details (error.sqlMessage, query strings), file system paths (err.path), and stack traces. The secure version implements centralized error handling that logs detailed errors server-side only while returning generic error messages to clients, preventing information disclosure to potential attackers.

Why it happens

Typical mistakes in app/data layers enable this vulnerability.

Root causes

Fixes

1

2

3

4

5

Detect This Vulnerability in Your Code

Sourcery automatically identifies sensitive data exposure through verbose api error messages and many other security issues in your codebase.