diff --git a/public/js/client.js b/public/js/client.js index 2e2a82b1..3e897263 100644 --- a/public/js/client.js +++ b/public/js/client.js @@ -1246,7 +1246,7 @@ function getPeerAvatar() { console.log('Direct join', { avatar: avatar }); - if (avatarDisabled || isBase64Avatar || !isImageURL(avatar)) { + if (avatarDisabled || isBase64Avatar || !isValidAvatarURL(avatar)) { return false; } return avatar; @@ -5285,7 +5285,7 @@ function setPeerAvatarImgName(videoAvatarImageId, peerName, peerAvatar) { videoAvatarImageElement.style.pointerEvents = 'none'; // If a valid avatar image URL is provided - if (peerAvatar && isImageURL(peerAvatar)) { + if (peerAvatar && isValidAvatarURL(peerAvatar)) { videoAvatarImageElement.setAttribute('src', peerAvatar); } // If not, use SVG based on the email validity @@ -5308,7 +5308,7 @@ function setPeerAvatarImgName(videoAvatarImageId, peerName, peerAvatar) { */ function setPeerChatAvatarImgName(avatar, peerName, peerAvatar) { const avatarImg = - peerAvatar && isImageURL(peerAvatar) + peerAvatar && isValidAvatarURL(peerAvatar) ? peerAvatar : isValidEmail(peerName) ? genGravatar(peerName) @@ -10599,7 +10599,7 @@ function handleSpeechTranscript(config) { const time_stamp = getFormatDate(new Date()); const avatar_image = - peer_avatar && isImageURL(peer_avatar) + peer_avatar && isValidAvatarURL(peer_avatar) ? peer_avatar : isValidEmail(peer_name) ? genGravatar(peer_name) @@ -10607,9 +10607,14 @@ function handleSpeechTranscript(config) { if (!isCaptionBoxVisible && transcriptShowOnMsg) showCaptionDraggable(); + // avatar_image is a user-controlled URL; do NOT interpolate it into + // insertAdjacentHTML — filterXSS encodes " to " which the HTML + // parser decodes back to " in attribute context (double-decode XSS). + // Use a temporary id and setAttribute instead. + const captionAvatarTmpId = `capt-av-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`; const msgHTML = `