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.