Any website can make its link render as a playable YouTube (or other provider) card: the embed is resolved from the page's own og:url #326

Closed
opened 2026-10-05 18:13:35 -04:00 by jared · 0 comments
Owner

UrlPreviewCard's resolveEmbed (src/app/components/url-preview/UrlPreviewCard.tsx:2464-2470) falls back to the preview's og:url when the message URL itself isn't a recognised embed: "Short copy-link links carry no id, so the embed is only resolvable from the homeserver's canonical og:url". It accepts any og:url, whatever the domain of the URL actually posted. og:url comes from the linked page's own <meta property="og:url">, fetched by the homeserver, so the page controls it.

Measured (preview routed to what a hostile page would serve: og:url = https://www.youtube.com/watch?v=dQw4w9WgXcQ, og:site_name = YouTube, og:title = Official Lotus Guild announcement). Bob posts new update https://evil.example/free-gift, and the timeline shows:

  • a full-width YouTube media card ("YouTube · Official Lotus Guild announcement · Watch now") with a Play button (screenshot);
  • Play embeds https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ?autoplay=1…, a video the attacker chose;
  • the card's "YouTube" label and title link to https://evil.example/free-gift.

So a phishing link can show up as a familiar, trusted video card whose clicks go to the attacker's site. #286 covers mismatched link text; this is the page itself choosing the card.

Fix: only use the og:url fallback when it points at the same provider as the posted link. Keep a small allow-map of the provider's own short-link hosts (youtu.be ↔ youtube.com, vm.tiktok.com/vt.tiktok.com ↔ tiktok.com, spotify.link ↔ open.spotify.com, on.soundcloud.com ↔ soundcloud.com, redd.it/reddit.com/r/…/s/ ↔ reddit.com, …). Otherwise render the plain card for the posted domain. Unit cases: evil.example + YouTube og:url → no embed; youtu.be/x + YouTube og:url → embed.

Screenshot

ogurl-spoof.png


Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny 30e2dbcd, cinny-desktop 8f67ec7, element-call 3b0050e8.

`UrlPreviewCard`'s `resolveEmbed` (src/app/components/url-preview/UrlPreviewCard.tsx:2464-2470) falls back to the preview's `og:url` when the message URL itself isn't a recognised embed: *"Short copy-link links carry no id, so the embed is only resolvable from the homeserver's canonical og:url"*. It accepts **any** `og:url`, whatever the domain of the URL actually posted. `og:url` comes from the linked page's own `<meta property="og:url">`, fetched by the homeserver, so the page controls it. **Measured** (preview routed to what a hostile page would serve: `og:url = https://www.youtube.com/watch?v=dQw4w9WgXcQ`, `og:site_name = YouTube`, `og:title = Official Lotus Guild announcement`). Bob posts `new update https://evil.example/free-gift`, and the timeline shows: - a full-width **YouTube** media card ("YouTube · Official Lotus Guild announcement · Watch now") with a Play button (screenshot); - **Play** embeds `https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ?autoplay=1…`, a video the attacker chose; - the card's "YouTube" label and title link to `https://evil.example/free-gift`. So a phishing link can show up as a familiar, trusted video card whose clicks go to the attacker's site. #286 covers mismatched link text; this is the page itself choosing the card. **Fix:** only use the `og:url` fallback when it points at the same provider as the posted link. Keep a small allow-map of the provider's own short-link hosts (`youtu.be` ↔ `youtube.com`, `vm.tiktok.com`/`vt.tiktok.com` ↔ `tiktok.com`, `spotify.link` ↔ `open.spotify.com`, `on.soundcloud.com` ↔ `soundcloud.com`, `redd.it`/`reddit.com/r/…/s/` ↔ `reddit.com`, …). Otherwise render the plain card for the posted domain. Unit cases: `evil.example` + YouTube `og:url` → no embed; `youtu.be/x` + YouTube `og:url` → embed. **Screenshot** ![ogurl-spoof.png](https://code.lotusguild.org/attachments/639179bb-07ff-464a-ba1d-c8c5550a5860) --- _Found in the October 2026 client audit (Playwright against a local Synapse + LiveKit stack, plus code reading). Code refs are at cinny `30e2dbcd`, cinny-desktop `8f67ec7`, element-call `3b0050e8`._
jared added the priority: lowsecurityarea: messaging labels 2026-10-05 18:13:35 -04:00
jared closed this issue 2026-10-18 05:54:22 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#326