diff --git a/server/src/http/middlewares/logMiddleware.ts b/server/src/http/middlewares/logMiddleware.ts index 6c83d2ddd8..016aaba7a0 100644 --- a/server/src/http/middlewares/logMiddleware.ts +++ b/server/src/http/middlewares/logMiddleware.ts @@ -1,14 +1,48 @@ import { FastifyError, FastifyLoggerOptions, FastifyReply, FastifyRequest, RawServerDefault } from "fastify" import { PinoLoggerOptions, ResSerializerReply } from "fastify/types/logger" -import { omitBy } from "lodash-es" import config from "@/config" -const withoutSensibleFields = (obj: object | null | undefined) => { - return omitBy(obj, (value, key) => { - const lower = key.toLowerCase() - return lower.indexOf("token") !== -1 || ["authorization", "password"].includes(lower) - }) +const withoutSensibleFields = (obj: unknown, seen: Set) => { + if (obj == null) return obj + + if (typeof seen === "object") { + if (seen.has(obj)) { + return "(ref)" + } + + seen.add(obj) + + if (Array.isArray(obj)) { + return obj.map((v) => withoutSensibleFields(v, seen)) + } + + if (obj instanceof Set) { + return Array.from(obj).map((v) => withoutSensibleFields(v, seen)) + } + + if (obj instanceof Map) { + return withoutSensibleFields(Object.fromEntries(obj.entries()), seen) + } + + return Object.fromEntries( + Object.entries(obj).map(([key, value]) => { + const lower = key.toLowerCase() + if (lower.indexOf("token") !== -1 || ["authorization", "password", "applicant_file_content"].includes(lower)) { + return [key, null] + } + + return [key, withoutSensibleFields(value, seen)] + }) + ) + } + + if (typeof obj === "string") { + // max 2Ko + return obj.length > 2000 ? obj.substring(0, 2_000) + "..." : obj + } + + return obj } export function logMiddleware(): FastifyLoggerOptions | PinoLoggerOptions | false { @@ -26,17 +60,17 @@ export function logMiddleware(): FastifyLoggerOptions | PinoLoggerOptions | fals remoteAddress: request.ip, remotePort: request.socket.remotePort, requestId: request.id, - headers: withoutSensibleFields(request.headers), + headers: withoutSensibleFields(request.headers, new Set()), query: request.query, params: request.params, - body: typeof request.body === "object" ? withoutSensibleFields(request.body) : null, + body: typeof request.body === "object" ? withoutSensibleFields(request.body, new Set()) : null, } }, res: (res: ResSerializerReply) => { return { responseTime: res.getResponseTime?.() ?? null, statusCode: res.statusCode, - headers: typeof res.getHeaders === "function" ? withoutSensibleFields(res.getHeaders()) : {}, + headers: typeof res.getHeaders === "function" ? withoutSensibleFields(res.getHeaders(), new Set()) : {}, } }, err: (err: FastifyError) => {