API Bugs

Sensitive Data Exposed in Error Response

When POST /api/orders receives an invalid payload, an unhandled exception causes the server to return an HTTP 500 response body containing a full stack trace with internal file paths, database table names, and query text. This information disclosure allows an attacker to map the application's internal structure and identify further attack targets.

HighBeginnerSecurity testingAPI testingManual testing

// UNDERSTAND

// Symptoms

  • A 500 Internal Server Error response body contains lines like 'at Object.<anonymous> (/app/src/orders/handler.js:42:15)'
  • The response body exposes the database table name (e.g. 'relation "tbl_order_items" does not exist') or a connection string fragment
  • Error messages include server-side file paths such as '/var/app/node_modules/...' or 'C:\inetpub\wwwroot\'
  • Internal variable names, SQL query fragments, or ORM method calls are visible in the response body

// Root Cause

  • The API framework's default unhandled-exception handler serialises the full exception object โ€” including the stack trace โ€” into the HTTP response body. No global error-handling middleware intercepts the exception before it reaches the framework's default handler.
  • The application is running with a development-mode error handler in the production or staging environment, where detailed error output is intentionally verbose for debugging purposes and was never switched off.

// Where It Appears

  • Any API endpoint that does not have a global error handler mapping unhandled exceptions to a safe generic response
  • Endpoints that interact with the database โ€” ORM or driver errors commonly include table names, column names, and query fragments
  • Applications that were recently promoted from development to staging without reviewing error-handler configuration
  • Microservices where each service configures its own error handler and one was missed

// REPRODUCE & TEST

// How to Reproduce

  1. 01Obtain a valid bearer token by authenticating as a standard user
  2. 02Send POST /api/orders with body { "customerId": null, "items": [] } and the bearer token โ€” this payload is designed to trigger a server-side exception by providing invalid values
  3. 03Read the HTTP response status code and the full response body
  4. 04Look for stack trace lines, file paths, database error messages, or internal identifiers in the body

// Test Data Needed

  • A valid bearer token for authentication
  • A request body that triggers an unhandled exception โ€” try null for required fields, extremely long strings, or unexpected types

// Manual Testing Ideas

  • Send requests with each required field set to null, an empty array, a very long string, or an unexpected type and observe whether any response contains a stack trace
  • Try sending a completely empty body {} to POST endpoints and note the response body for any internal detail
  • Test with an invalid auth token to trigger auth-related exceptions โ€” some auth middleware errors expose internal paths
  • Check the Content-Type header on 500 responses โ€” text/html often contains a debug page with a full trace; application/json may embed it in an error field
  • Compare error responses in the staging environment against a known production build to confirm the verbose handler is not deployed to production

// API Testing Ideas

  • Obtain a valid bearer token
  • Send POST /api/orders with body { "customerId": null, "items": [] } and the bearer token
  • Assert the HTTP status is 400 Bad Request or 422 Unprocessable Entity โ€” not 500
  • Assert the response body does NOT contain the strings 'at Object', 'node_modules', 'stack', or any file path pattern (e.g. '/.*/src/')
  • Repeat with an empty body {} and assert the same conditions

// Automation Idea

Send POST /api/orders with several invalid payloads: null required fields, empty body, unexpected types. For each, assert the HTTP status is 4xx (not 500). Also assert the response body does not match a stack-trace pattern (e.g. /at \w+ \(.*:\d+:\d+\)/). Any 500 response with a stack trace in the body should fail the test.

// Expected Result

POST /api/orders with invalid input returns 400 Bad Request or 422 Unprocessable Entity with a safe, generic error message such as { "error": "Invalid request body" }. No internal paths, table names, or stack frames are included.

// Actual Result (Example)

POST /api/orders with body { "customerId": null, "items": [] } returns HTTP 500 with a response body containing: 'TypeError: Cannot read properties of null (reading \'id\') at validateOrder (/app/src/orders/validator.js:18:22) at Object.<anonymous> (/app/src/orders/handler.js:42:15)'.

// REPORT IT

Example Bug Report

Title
POST /api/orders with null customerId returns 500 with full stack trace in response body
Severity
High
Environment
Staging environment Postman Valid bearer token Endpoint: POST /api/orders
Steps to Reproduce
  1. 01Authenticate as a standard user and copy the bearer token
  2. 02Send POST /api/orders with body { "customerId": null, "items": [] } and the Authorization header
  3. 03Read the HTTP response status code and full response body
Expected Result
The API returns 400 Bad Request or 422 with a safe error message. No stack trace or internal paths are included.
Actual Result
The API returns 500 Internal Server Error. The response body contains a full Node.js stack trace including internal file paths: 'at validateOrder (/app/src/orders/validator.js:18:22)'.
Impact
An attacker can enumerate the application's internal file structure, module names, and database schema by triggering exceptions. This information directly aids further attacks such as path traversal, SQL injection targeting, and dependency exploitation.

// RELATED