chore: sanitize sensitive data from logs and error messages

This commit is contained in:
Nicolas Meienberger
2025-10-17 21:11:12 +02:00
parent ae592481af
commit c8fc5a1273
4 changed files with 31 additions and 10 deletions

View File

@@ -1,12 +1,12 @@
import * as fs from "node:fs/promises";
import * as os from "node:os";
import { BACKEND_STATUS, type BackendConfig } from "@ironmount/schemas";
import type { VolumeBackend } from "../backend";
import { logger } from "../../../utils/logger";
import { withTimeout } from "../../../utils/timeout";
import { OPERATION_TIMEOUT } from "../../../core/constants";
import { toMessage } from "../../../utils/errors";
import { logger } from "../../../utils/logger";
import { getMountForPath } from "../../../utils/mountinfo";
import { withTimeout } from "../../../utils/timeout";
import type { VolumeBackend } from "../backend";
import { createTestFile, executeMount, executeUnmount } from "../utils/backend-utils";
const mount = async (config: BackendConfig, path: string) => {

View File

@@ -1,17 +1,19 @@
import { ConflictError, NotFoundError } from "http-errors-enhanced";
import { sanitizeSensitiveData } from "./sanitize";
export const handleServiceError = (error: unknown) => {
if (error instanceof ConflictError) {
return { message: error.message, status: 409 as const };
return { message: sanitizeSensitiveData(error.message), status: 409 as const };
}
if (error instanceof NotFoundError) {
return { message: error.message, status: 404 as const };
return { message: sanitizeSensitiveData(error.message), status: 404 as const };
}
return { message: toMessage(error), status: 500 as const };
return { message: sanitizeSensitiveData(toMessage(error)), status: 500 as const };
};
export const toMessage = (err: unknown): string => {
return err instanceof Error ? err.message : String(err);
const message = err instanceof Error ? err.message : String(err);
return sanitizeSensitiveData(message);
};

View File

@@ -1,4 +1,5 @@
import { createLogger, format, transports } from "winston";
import { sanitizeSensitiveData } from "./sanitize";
const { printf, combine, colorize } = format;
@@ -14,14 +15,14 @@ const winstonLogger = createLogger({
const log = (level: "info" | "warn" | "error" | "debug", messages: unknown[]) => {
const stringMessages = messages.flatMap((m) => {
if (m instanceof Error) {
return [m.message, m.stack];
return [sanitizeSensitiveData(m.message), m.stack ? sanitizeSensitiveData(m.stack) : undefined].filter(Boolean);
}
if (typeof m === "object") {
return JSON.stringify(m, null, 2);
return sanitizeSensitiveData(JSON.stringify(m, null, 2));
}
return m;
return sanitizeSensitiveData(String(m));
});
winstonLogger.log(level, stringMessages.join(" "));

View File

@@ -0,0 +1,18 @@
/**
* Sanitizes sensitive information from strings
* This removes passwords and credentials from logs and error messages
*/
export const sanitizeSensitiveData = (text: string): string => {
let sanitized = text.replace(/\b(pass|password)=([^\s,]+)/gi, "$1=***");
sanitized = sanitized.replace(/\/\/([^:@\s]+):([^@\s]+)@/g, "//$1:***@");
sanitized = sanitized.replace(/(\S+)\s+(\S+)\s+(\S+)/g, (match, url, user, _pass) => {
if (url.startsWith("http://") || url.startsWith("https://")) {
return `${url} ${user} ***`;
}
return match;
});
return sanitized;
};