You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Post-Express-5 cleanup promised in v6.14.0 release notes. 175 async
handlers across 21 route files now use a single asyncHandler() wrapper
instead of the duplicated try/catch + res.status(500).json({ error:
err.message }) boilerplate. Net diff: -521 LOC.
Non-obvious security fix discovered in the process:
The central error middleware at src/server.js:168 sanitizes 5xx
responses (scrubs /home/ and /data/ paths, redacts credentials in
URLs, replaces raw err.message with "Internal server error"). But
the try/catch wrappers in 21 route files were BYPASSING that
sanitizer by calling res.status(500).json({ error: err.message })
directly.
After this release all generic 500s go through the sanitizer — no
more accidental path/credential leaks in error messages.
What's left alone (by design): handlers with dynamic status codes,
non-generic catch shapes, 4xx-mapping logic, SSE callbacks, or
business-logic in the catch block. 10 legitimate res.status(500)
call sites remain — all inspected and confirmed non-generic.
Tests: 740 passing / 4 skipped (unchanged).
Lint: zero warnings on src/routes/.
Post-v6.14.0 cleanup promised in the previous release notes: consolidate the try/catch + `res.status(500).json({ error: err.message })` boilerplate into a single `asyncHandler(fn)` wrapper. 175 handlers migrated across 21 route files. **Net diff: −521 LOC.**
8
+
9
+
### What this actually fixes (the non-obvious win)
10
+
11
+
Docker Dash's central error middleware at [src/server.js:168-190](src/server.js#L168-L190) already **sanitizes** 5xx responses — scrubs home/data paths, redacts URL credentials, and replaces the raw `err.message` with `'Internal server error'`. Until now, the try/catch wrappers in 21 route files **bypassed** that sanitization by calling `res.status(500).json({ error: err.message })` directly. So any backend error surfacing through those handlers was leaking the raw exception string to the client.
12
+
13
+
After this release, all generic 500 responses go through the central middleware → **no more accidental path or credential exposure in error messages.**
14
+
15
+
This wasn't the stated goal of the refactor (the goal was LOC reduction), but it's the more important outcome. Worth calling out for anyone reading the CHANGELOG looking for security-relevant deltas.
- Behavior-preserving: clients keep receiving `{ error: "<sanitized message>" }` with 5xx status — the sanitization itself is the only behavior change, and that's an upgrade (not a downgrade) from the previous accidental leak.
BACKLOG P2 item closed. Deep-spec ([plans/deep-spec-express5-migration.md](plans/deep-spec-express5-migration.md)) predicted 3-5h based on evidence that the codebase was already v5-idiomatic. Actual execution cost ~2h with one mid-flight snag (see below).
{type: 'security',text: 'Non-obvious security fix discovered during the refactor: Docker Dash\'s central error middleware at src/server.js:168 already sanitizes 5xx responses (scrubs /home/ and /data/ paths, redacts credentials in URLs, replaces raw err.message with "Internal server error"). The 21 route files with try/catch wrappers were BYPASSING this sanitization by calling res.status(500).json({ error: err.message }) directly — leaking raw exception text to clients. All generic 500 handlers now go through the sanitizer.'},
18
+
{type: 'improvement',text: 'Post-Express-5 cleanup: new src/utils/asyncHandler.js (4 lines) wraps async handlers so rejected promises auto-forward to the error middleware. 175 handler invocations migrated across 21 route files. Net diff: -521 LOC of boilerplate gone.'},
19
+
{type: 'improvement',text: 'Handlers with dynamic status codes, non-generic catch shapes (extra fields), 4xx-mapping logic, SSE streaming, or business-logic in the catch block were LEFT ALONE intentionally — those aren\'t boilerplate, they\'re intentional error handling. 10 legitimate res.status(500) call sites remain.'},
20
+
{type: 'improvement',text: 'Tests: 740 passing / 4 skipped (unchanged). Lint: zero warnings on src/routes/.'},
0 commit comments