From 693d72431b406e2b3c57af28b0ece87a791c90fd Mon Sep 17 00:00:00 2001 From: Keysat Date: Sat, 13 Jun 2026 18:22:00 -0500 Subject: [PATCH] Return clean JSON for body-parser/unhandled errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Malformed JSON request bodies fell through to Express's default error handler, which renders an HTML page including the local-filesystem stack trace (info leak). Add a final error-handling middleware: JSON 400 for entity.parse.failed, 413 for entity.too.large, generic 500 otherwise — closing the stack-trace leak on every propagated error, not just JSON. --- server/index.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/server/index.js b/server/index.js index ae93092..1ae1d1d 100644 --- a/server/index.js +++ b/server/index.js @@ -105,6 +105,22 @@ app.get("/", (_req, res) => { res.redirect("/dashboard.html"); }); +// Error handler (must be last). Without it, body-parser parse failures +// and any other propagated error fall through to Express's default +// handler, which renders an HTML page including the local-filesystem +// stack trace — an info leak. Return clean JSON instead. +app.use((err, _req, res, next) => { + if (res.headersSent) return next(err); // mid-stream (SSE) — can't rewrite + if (err?.type === "entity.parse.failed") { + return res.status(400).json({ error: "invalid JSON body" }); + } + if (err?.type === "entity.too.large") { + return res.status(413).json({ error: "request body too large" }); + } + console.error("[relay] unhandled error:", err?.message || err); + return res.status(500).json({ error: "internal error" }); +}); + const HOSTNAME = process.env.HOSTNAME || "0.0.0.0"; app.listen(PORT, HOSTNAME, () => { console.log(`[relay] listening on http://${HOSTNAME}:${PORT}`);