diff --git a/app/components/Compare/PackageSelector.vue b/app/components/Compare/PackageSelector.vue index dd1d893a99..3679a9ba10 100644 --- a/app/components/Compare/PackageSelector.vue +++ b/app/components/Compare/PackageSelector.vue @@ -301,7 +301,7 @@ onClickOutside(containerRef, () => { v-if="result.description" class="text-xs text-fg-muted truncate mt-0.5 w-full block" > - {{ decodeHtmlEntities(result.description) }} + {{ stripHtmlTags(decodeHtmlEntities(result.description)) }} diff --git a/app/components/Package/TableRow.vue b/app/components/Package/TableRow.vue index 3e3768602b..267b7f1b91 100644 --- a/app/components/Package/TableRow.vue +++ b/app/components/Package/TableRow.vue @@ -69,7 +69,7 @@ const allMaintainersText = computed(() => { v-if="isColumnVisible('description')" class="py-2 px-3 text-sm text-fg-muted max-w-xs truncate" > - {{ decodeHtmlEntities(pkg.description || '-') }} + {{ stripHtmlTags(decodeHtmlEntities(pkg.description || '-')) }} diff --git a/server/utils/readme.ts b/server/utils/readme.ts index b7c8fb266b..e3d337ecec 100644 --- a/server/utils/readme.ts +++ b/server/utils/readme.ts @@ -3,7 +3,7 @@ import sanitizeHtml from 'sanitize-html' import { hasProtocol } from 'ufo' import type { ReadmeResponse, TocItem } from '#shared/types/readme' import { convertBlobOrFileToRawUrl, type RepositoryInfo } from '#shared/utils/git-providers' -import { decodeHtmlEntities } from '#shared/utils/html' +import { decodeHtmlEntities, stripHtmlTags } from '#shared/utils/html' import { convertToEmoji } from '#shared/utils/emoji' import { toProxiedImageUrl } from '#server/utils/image-proxy' @@ -194,22 +194,6 @@ const ALLOWED_ATTR: Record = { 'p': ['align'], } -/** - * Strip all HTML tags from a string, looping until stable to prevent - * incomplete sanitization from nested/interleaved tags - * (e.g. `ipt>` → `