From 04a4ef9c85c2f20e2a89ee79492602bccf69e1e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 19 Apr 2026 20:18:55 +0000 Subject: [PATCH] =?UTF-8?q?fix(community):=20CR=20fixes=20=E2=80=94=20sani?= =?UTF-8?q?tize=20OG=20cover=20URLs=20+=20Hero=20=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E5=8E=BB=E5=B5=8C=E5=A5=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot CR 指出的两条: PR #315 Hero.tsx:119 —— + {t("cta.access")} - + {t("cta.feed")} diff --git a/app/feed/components/LinkCard.tsx b/app/feed/components/LinkCard.tsx index 7a71bcc..cd1c639 100644 --- a/app/feed/components/LinkCard.tsx +++ b/app/feed/components/LinkCard.tsx @@ -10,6 +10,7 @@ import { useTranslations } from "next-intl"; import type { SharedLinkView } from "@/app/feed/types"; import { ReportButton } from "@/app/feed/components/ReportButton"; import { Badge } from "@/components/ui/badge"; +import { sanitizeMediaUrl } from "@/lib/url-safety"; interface LinkCardProps { link: SharedLinkView; @@ -27,6 +28,8 @@ function getHostInitial(host: string): string { export function LinkCard({ link, categoryLabel, isLoggedIn }: LinkCardProps) { const t = useTranslations("feed.card"); + // defense-in-depth:过白名单协议拦 javascript:/data:,后端 UrlNormalizer 是第一道,这里是第二道 + const safeOgCover = sanitizeMediaUrl(link.ogCover); return (
  • @@ -39,14 +42,14 @@ export function LinkCard({ link, categoryLabel, isLoggedIn }: LinkCardProps) { aria-label={link.ogTitle ?? link.url} > {/* OG 封面 / 占位块 */} - {link.ogCover && !link.ogFetchFailed ? ( + {safeOgCover && !link.ogFetchFailed ? ( // next/image 全站 unoptimized:true,用 img 即可(与 events 页一致)。 // referrerPolicy="no-referrer":微信 mmbiz.qpic.cn 防盗链会检查 Referer, // 非 mp.weixin.qq.com 来源直接返回"未经允许使用"裂图;不发 Referer 时 // 反而放行(微信客户端内打开文章浏览器也不发 Referer)。 // eslint-disable-next-line @next/next/no-img-element