Split out of #1477 (item 1) for separate tracking, since it has the clearest security implications of that batch.
src/response.ts:19 — when a handler's promise rejects, only typeof r === "number" is special-cased into an HTTPError:
(r) => toResponse(typeof r === "number" ? new HTTPError({ status: r }) : r, event, config),
Any other non-Error rejection value re-enters toResponse as if it were a normal handler return value, producing a successful 200 response whose body is the thrown value:
app.get("/boom", () => {
throw { secret: "db-password", status: 403 };
});
// → HTTP 200, content-type: application/json
// → body: {"secret":"db-password","status":403}
Also verified on current main (75ac47d):
throw "not-an-error" → 200 with body not-an-error
throw undefined → 200 empty response
A caught-and-rethrown non-Error from a database driver or third-party library leaks its full contents to the client with a success status, and onError / unhandled logging never see it. Expected behavior: non-Error rejections should be wrapped into an unhandled 500 HTTPError (e.g. HTTPError.isError(r) ? r : new HTTPError(...) with the value attached as non-public detail), consistent with how thrown Error instances are handled in prepareResponse.
Split out of #1477 (item 1) for separate tracking, since it has the clearest security implications of that batch.
src/response.ts:19— when a handler's promise rejects, onlytypeof r === "number"is special-cased into anHTTPError:Any other non-
Errorrejection value re-enterstoResponseas if it were a normal handler return value, producing a successful 200 response whose body is the thrown value:Also verified on current
main(75ac47d):throw "not-an-error"→200with bodynot-an-errorthrow undefined→200empty responseA caught-and-rethrown non-
Errorfrom a database driver or third-party library leaks its full contents to the client with a success status, andonError/unhandledlogging never see it. Expected behavior: non-Errorrejections should be wrapped into an unhandled 500HTTPError(e.g.HTTPError.isError(r) ? r : new HTTPError(...)with the value attached as non-public detail), consistent with how thrownErrorinstances are handled inprepareResponse.