From b0e78086f42e4672eae6fad58ad89c23cb0330f0 Mon Sep 17 00:00:00 2001 From: Bennet Gallein Date: Sat, 14 Feb 2026 10:30:20 +0100 Subject: [PATCH] feat: anonymize IPs via HMAC before persisting to MongoDB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GDPR compliance — IPs are HMAC-SHA256'd (truncated to 16 hex chars) before being pushed to the Redis queue, so only pseudonymous tokens are ever stored. Co-Authored-By: Claude Opus 4.6 --- server/middleware/requestLogger.ts | 2 +- server/utils/requestLogger.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/server/middleware/requestLogger.ts b/server/middleware/requestLogger.ts index 452c986c..6d1bdab4 100644 --- a/server/middleware/requestLogger.ts +++ b/server/middleware/requestLogger.ts @@ -8,7 +8,7 @@ export default defineEventHandler((event) => { event.node.res.on("finish", () => { logRequest({ - ip, + ip: anonymizeIp(ip), path, method, statusCode: event.node.res.statusCode, diff --git a/server/utils/requestLogger.ts b/server/utils/requestLogger.ts index aff978b7..df1a78fb 100644 --- a/server/utils/requestLogger.ts +++ b/server/utils/requestLogger.ts @@ -1,3 +1,5 @@ +import { createHmac } from "node:crypto"; + export interface RequestLogEntry { ip: string; path: string; @@ -7,6 +9,11 @@ export interface RequestLogEntry { timestamp: string; } +export function anonymizeIp(ip: string): string { + const secret = useRuntimeConfig().adminPassword || "default-hmac-key"; + return createHmac("sha256", secret).update(ip).digest("hex").slice(0, 16); +} + export function logRequest(data: RequestLogEntry): void { try { const redis = getRedis();