From fb66c0ed9071c3f081b30999d07bdcdc5d945b9d Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 18 Jun 2026 19:24:52 -0400 Subject: [PATCH] fix(privacy): sanitize console error/warn to prevent PII leakage Replace raw error object logging (which may contain Matrix event payloads, user IDs, or message bodies) with e.message-only strings in three files: - CallEmbed.ts: state update and event widget feed errors - msgContent.ts: image/video element load failures and thumb errors - RoomInput.tsx: GIF send failure Co-Authored-By: Claude Sonnet 4.6 --- src/app/features/room/RoomInput.tsx | 2 +- src/app/features/room/msgContent.ts | 6 +++--- src/app/plugins/call/CallEmbed.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/features/room/RoomInput.tsx b/src/app/features/room/RoomInput.tsx index eaba3b937..0afe767a7 100644 --- a/src/app/features/room/RoomInput.tsx +++ b/src/app/features/room/RoomInput.tsx @@ -725,7 +725,7 @@ export const RoomInput = forwardRef( info: { mimetype: 'image/gif', w, h, size: blob.size }, }); } catch (e) { - console.error('GIF send failed', e); + console.error('GIF send failed:', e instanceof Error ? e.message : 'unknown error'); if (!alive()) return; setGifError('Failed to send GIF. Please try again.'); setTimeout(() => setGifError(null), 4000); diff --git a/src/app/features/room/msgContent.ts b/src/app/features/room/msgContent.ts index 3670b4dfd..b2786b29e 100644 --- a/src/app/features/room/msgContent.ts +++ b/src/app/features/room/msgContent.ts @@ -50,7 +50,7 @@ export const getImageMsgContent = async ( ): Promise => { const { file, originalFile, encInfo, metadata } = item; const [imgError, imgEl] = await to(loadImageElement(getImageFileUrl(originalFile))); - if (imgError) console.warn(imgError); + if (imgError) console.warn('Failed to load image element:', imgError.message); const content: IContent = { msgtype: MsgType.Image, @@ -85,7 +85,7 @@ export const getVideoMsgContent = async ( const { file, originalFile, encInfo, metadata } = item; const [videoError, videoEl] = await to(loadVideoElement(getVideoFileUrl(originalFile))); - if (videoError) console.warn(videoError); + if (videoError) console.warn('Failed to load video element:', videoError.message); const content: IContent = { msgtype: MsgType.Video, @@ -109,7 +109,7 @@ export const getVideoMsgContent = async ( scaleYDimension(videoEl.videoWidth, 512, videoEl.videoHeight), ); } - if (thumbError) console.warn(thumbError); + if (thumbError) console.warn('Failed to generate video thumbnail:', thumbError.message); content.info = { ...getVideoInfo(videoEl, file), ...thumbContent, diff --git a/src/app/plugins/call/CallEmbed.ts b/src/app/plugins/call/CallEmbed.ts index 4773ac4a1..7ab08e40d 100644 --- a/src/app/plugins/call/CallEmbed.ts +++ b/src/app/plugins/call/CallEmbed.ts @@ -390,7 +390,7 @@ export class CallEmbed { if (this.call === null) return; const raw = ev.getEffectiveEvent(); this.call.feedStateUpdate(raw as IRoomEvent).catch((e) => { - console.error('Error sending state update to widget: ', e); + console.error('Error sending state update to widget:', e instanceof Error ? e.message : 'unknown error'); }); } @@ -496,7 +496,7 @@ export class CallEmbed { } else { const raw = ev.getEffectiveEvent(); this.call.feedEvent(raw as IRoomEvent).catch((e) => { - console.error('Error sending event to widget: ', e); + console.error('Error sending event to widget:', e instanceof Error ? e.message : 'unknown error'); }); } }