fix(community): OG 封面 referrerPolicy=no-referrer 规避微信防盗链裂图#316
fix(community): OG 封面 referrerPolicy=no-referrer 规避微信防盗链裂图#316longsizhuo merged 1 commit intomainfrom
Conversation
微信 mmbiz.qpic.cn(以及知乎 pic* / 小红书 ci.xiaohongshu.com)对图片请求检查 Referer,非 mp.weixin.qq.com 来源直接返回"此图片来自微信公众平台未经允许不可 使用"的裂图。不发 Referer 时反而放行(微信客户端打开文章时浏览器也不发)。 改动: - LinkCard: <img> 加 referrerPolicy="no-referrer" - /admin/community: 原来的 next/image 改成 <img> + referrerPolicy (顺手规避 next/image remotePatterns 对任意外站域名的限制——Copilot CR 之前 指出过,当时用 unoptimized 绕过,现在统一切 <img> 更干净)
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR fixes broken OG cover images in community link cards (e.g., WeChat public account covers) by preventing the browser from sending a Referer header, which avoids anti-hotlinking “裂图” responses.
Changes:
- Add
referrerPolicy="no-referrer"to OG cover rendering in the feedLinkCard. - Replace
next/imagewith native<img>on/admin/communityand addreferrerPolicy="no-referrer"(also avoidingremotePatternslimitations).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| app/feed/components/LinkCard.tsx | Adds referrerPolicy="no-referrer" to OG cover <img> in feed cards. |
| app/admin/community/page.tsx | Switches OG cover thumbnail from next/image to <img> and applies referrerPolicy="no-referrer". |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <img | ||
| src={link.ogCover} | ||
| alt={link.ogTitle ?? link.host} | ||
| referrerPolicy="no-referrer" | ||
| className="w-full aspect-[16/9] object-cover border-b border-[var(--foreground)]" |
There was a problem hiding this comment.
link.ogCover 直接作为 <img src> 渲染,绕过了仓库里用于媒体 URL scheme 白名单的 sanitizeMediaUrl(lib/url-safety.ts 里明确要求后端/用户输入的媒体 URL 渲染前必须过白名单)。建议在渲染前先计算 const safeOgCover = sanitizeMediaUrl(link.ogCover),并仅在 safeOgCover 非空时渲染封面(否则走占位块)。
| <img | ||
| src={link.ogCover} | ||
| alt={link.ogTitle ?? link.url} | ||
| fill | ||
| sizes="160px" | ||
| className="object-cover" | ||
| unoptimized | ||
| referrerPolicy="no-referrer" | ||
| className="absolute inset-0 w-full h-full object-cover" |
There was a problem hiding this comment.
这里把 OG 封面从 next/image 改为原生 <img> 后,link.ogCover 会以未校验的 URL 直接进入 src。仓库已有 sanitizeMediaUrl 用于拦截 javascript:/data: 等协议(lib/url-safety.ts),建议在渲染前对 link.ogCover 做白名单过滤,并在返回 null 时回退到占位内容。
Copilot CR 指出的两条: PR #315 Hero.tsx:119 —— <a> 包 <button> 是嵌套交互元素(HTML 无效 + a11y 问题) 修法:把 <Link> 直接渲染成按钮样式,不再嵌套 <button> PR #316 LinkCard.tsx:52 / admin/community/page.tsx:143 —— OG 封面 URL 直接进 <img src> 没过白名单。 修法:用 lib/url-safety.ts 的 sanitizeMediaUrl 兜底,拦 javascript:/data: 协议 (后端 UrlNormalizer 是第一道防线,前端 sanitize 是 defense-in-depth)
Copilot CR 指出的两条: PR #315 Hero.tsx:119 —— <a> 包 <button> 是嵌套交互元素(HTML 无效 + a11y 问题) 修法:把 <Link> 直接渲染成按钮样式,不再嵌套 <button> PR #316 LinkCard.tsx:52 / admin/community/page.tsx:143 —— OG 封面 URL 直接进 <img src> 没过白名单。 修法:用 lib/url-safety.ts 的 sanitizeMediaUrl 兜底,拦 javascript:/data: 协议 (后端 UrlNormalizer 是第一道防线,前端 sanitize 是 defense-in-depth) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
症状
/feed 列表里微信公众号卡片封面显示裂图:"此图片来自微信公众平台未经允许不可使用"。
原因
微信 `mmbiz.qpic.cn` 对图片请求检查 Referer:
知乎 `pic*.zhimg.com` / 小红书 `ci.xiaohongshu.com` 同样策略。
改动
验证