From d2edb93340308c588f035b2b1e45b2607c9e7d2a Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:29:17 +0200 Subject: [PATCH] General: Better validation for HTML attributes (#6892) --- .../common/helpers/renderTextWithEntities.tsx | 8 +++- .../middle/composer/helpers/cleanHtml.ts | 32 +++++++++++++-- .../middle/composer/helpers/customEmoji.ts | 41 +++++++++++-------- .../composer/hooks/useMentionTooltip.ts | 5 ++- src/config.ts | 2 +- src/serviceWorker/download.ts | 30 ++++++++++++-- src/util/parseHtmlAsFormattedText.ts | 29 ++++--------- 7 files changed, 99 insertions(+), 48 deletions(-) diff --git a/src/components/common/helpers/renderTextWithEntities.tsx b/src/components/common/helpers/renderTextWithEntities.tsx index 605100c72..721669192 100644 --- a/src/components/common/helpers/renderTextWithEntities.tsx +++ b/src/components/common/helpers/renderTextWithEntities.tsx @@ -7,9 +7,11 @@ import type { TextPart, ThreadId } from '../../../types'; import type { TextFilter } from './renderText'; import { ApiMessageEntityTypes } from '../../../api/types'; +import { ensureProtocol } from '../../../util/browser/url'; import buildClassName from '../../../util/buildClassName'; import { copyTextToClipboard } from '../../../util/clipboard'; import { buildFormattedDateHtml } from '../../../util/dates/formattedDate'; +import { escapeHtmlAttribute } from '../../middle/composer/helpers/cleanHtml'; import { buildCustomEmojiHtmlFromEntity } from '../../middle/composer/helpers/customEmoji'; import renderText from './renderText'; @@ -753,7 +755,7 @@ function processEntityAsHtml( case ApiMessageEntityTypes.TextUrl: return `${renderedContent}`; @@ -781,6 +783,10 @@ function getLinkUrl(entityContent: string, entity: ApiMessageEntity) { return type === ApiMessageEntityTypes.TextUrl && entity.url ? entity.url : entityContent; } +function getHtmlLinkUrl(entityContent: string, entity: ApiMessageEntity) { + return escapeHtmlAttribute(ensureProtocol(getLinkUrl(entityContent, entity))); +} + function handleBotCommandClick(e: React.MouseEvent) { getActions().sendBotCommand({ command: e.currentTarget.innerText }); } diff --git a/src/components/middle/composer/helpers/cleanHtml.ts b/src/components/middle/composer/helpers/cleanHtml.ts index 45962da36..4c9cd03ba 100644 --- a/src/components/middle/composer/helpers/cleanHtml.ts +++ b/src/components/middle/composer/helpers/cleanHtml.ts @@ -2,12 +2,32 @@ import { ApiMessageEntityTypes } from '../../../../api/types'; import { DEBUG } from '../../../../config'; import cleanDocsHtml from '../../../../lib/cleanDocsHtml'; -import { ENTITY_CLASS_BY_NODE_NAME } from '../../../../util/parseHtmlAsFormattedText'; const STYLE_TAG_REGEX = /