Take a link preview's host as a domain name, not an address

A browser rewrites the many spellings of an address into one before it
fetches, so "http://2130706433/rooms/1" arrives at 127.0.0.1 while a
comparison here still reads the digits. A preview names a page on the
public internet, so require its host to look like a domain name and leave
the rewriting race alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186eyzivcTn6wqjEE4Wnxdt
This commit is contained in:
Rosa Gutierrez
2026-09-11 20:21:01 +02:00
parent 32e3e5aea8
commit 9e19658ee0
2 changed files with 19 additions and 1 deletions
+9 -1
View File
@@ -42,11 +42,19 @@ class ActionText::Attachment::OpengraphEmbed
# while a browser still unescapes it back to us, so an escaped host is out
# too, and neither case is anything an unfurl could have produced.
def elsewhere?(host)
return false if host.blank? || host.include?("%")
return false unless named_host?(host)
canonical_host(host) != canonical_host(Current.request_host.to_s)
end
# A preview names a page on the public internet, so its host is a domain
# name: it has a dot and a letter in it, and no escapes. A bare address is
# not one, and a browser rewrites the many spellings of an address into a
# single one before it fetches, which is a race a comparison here loses.
def named_host?(host)
host.present? && host.exclude?("%") && host.include?(".") && host.match?(/[a-z]/i)
end
def canonical_host(host)
host.downcase.delete_suffix(".")
end
@@ -36,6 +36,16 @@ class ActionText::Attachment::OpengraphEmbedTest < ActiveSupport::TestCase
end
end
test "drops a link and an image on a bare address rather than a domain name" do
[ "http://127.0.0.1/rooms/1", "http://2130706433/rooms/1", "http://0177.0.0.1/rooms/1",
"http://[::1]/rooms/1", "http://localhost/rooms/1", "https://203.0.113.10/image.png" ].each do |value|
embed = embed_from href: value, url: value
assert_nil embed.href, "expected #{value.inspect} to be dropped as a link"
assert_nil embed.url, "expected #{value.inspect} to be dropped as an image"
end
end
test "renders the image and the link when both are web URLs" do
html = render_embed href: "https://example.com/page", url: "https://example.com/image.png"