Skip to content

security(controllers): raw Sequelize/pg error text leaked to clients in 5xx bodies #139

@CryptoJones

Description

@CryptoJones

Problem

Every controller in app/controllers/ had try/catch blocks that returned the caught error verbatim:

return res.status(500).json({ message: "Error!", error: String(error) });

That error field surfaces raw internal text to the client:

  • "value too long for type character varying(255)" — leaks column names + length limits, useful for SQL-injection / schema enumeration
  • "connection to server at \"db\" (10.0.0.5) failed" — leaks internal hostnames and IPs
  • "duplicate key value violates unique constraint \"some_table_pkey\"" — leaks table + constraint names
  • pg error codes that reveal which backend you're on, etc.

The global error-handler in app/middleware/error-handler.js (#22) was already written to NOT surface this detail:

5xx: always generic. The full error lands in the log; clients get a stable shape + a requestId to correlate.

…but the per-controller catches intercept the error before it can reach the global path, so the policy is silently bypassed across all 17 controllers — 137 occurrences total of the leak.

Proposed fix

Strip , error: String(error) from every 5xx return across the 17 controllers. The controllers already log the full error via log.error({ err: error }, …), so the operator-side signal is unchanged — only the client-facing body loses the leak.

One static-string variant in customercontroller.js (error: "Sequelize Op not available") is also removed since it violated the same policy.

Pin the policy with a source-level regression test (tests/unit/controller-error-shape.test.js) that does test.each() over every controller file and asserts the pattern doesn't reappear. Future copy-paste of the old shape will fail CI.

Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions