Production leaks server stack traces in tRPC error responses #23

Open
opened 2026-07-31 20:38:20 +00:00 by forgejo-admin · 0 comments

Error responses from the production API include a full stack field, exposing internal paths and framework internals to any unauthenticated caller.

Reproduce — note this needs no valid credentials:

curl -H 'Authorization: Bearer garbage' \
  'https://www.lunacycle.net/api/getActiveMonth?batch=1&input=%7B%7D'

-> [{"error":{"message":"Authentication required","code":-32001,
     "data":{"code":"UNAUTHORIZED","httpStatus":401,
       "stack":"TRPCError: Authentication required\n
         at <anonymous> (/$bunfs/root/server-linux-x64:57:55145)\n
         at <anonymous> (/$bunfs/root/server-linux-x64:57:55264)\n ...

Impact. Standard information disclosure. Stack traces reveal internal structure and framework versions, and give an attacker feedback while probing. Minified single-file bundle paths (/$bunfs/root/server-linux-x64) limit the damage somewhat, but line/column offsets still leak, and any future unminified or differently-packaged build would leak more.

tRPC omits stack in production when NODE_ENV=production; it is presumably unset or non-production in the deployed unit. Worth confirming how the systemd unit is built rather than assuming — the fix may be an env var in the celilo deploy rather than a code change, or an explicit errorFormatter that strips stack regardless of environment. The explicit formatter is the more robust option since it does not depend on deployment env being right.

Found while investigating the first-ever production run of the smoke checks (#20).

Error responses from the production API include a full `stack` field, exposing internal paths and framework internals to any unauthenticated caller. Reproduce — note this needs no valid credentials: ``` curl -H 'Authorization: Bearer garbage' \ 'https://www.lunacycle.net/api/getActiveMonth?batch=1&input=%7B%7D' -> [{"error":{"message":"Authentication required","code":-32001, "data":{"code":"UNAUTHORIZED","httpStatus":401, "stack":"TRPCError: Authentication required\n at <anonymous> (/$bunfs/root/server-linux-x64:57:55145)\n at <anonymous> (/$bunfs/root/server-linux-x64:57:55264)\n ... ``` **Impact.** Standard information disclosure. Stack traces reveal internal structure and framework versions, and give an attacker feedback while probing. Minified single-file bundle paths (`/$bunfs/root/server-linux-x64`) limit the damage somewhat, but line/column offsets still leak, and any future unminified or differently-packaged build would leak more. tRPC omits `stack` in production when `NODE_ENV=production`; it is presumably unset or non-production in the deployed unit. Worth confirming how the systemd unit is built rather than assuming — the fix may be an env var in the celilo deploy rather than a code change, or an explicit `errorFormatter` that strips `stack` regardless of environment. The explicit formatter is the more robust option since it does not depend on deployment env being right. Found while investigating the first-ever production run of the smoke checks (#20).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
celilo/lunacycle#23
No description provided.