Escape the OpenGraph image URL in link previews

Pasting a link builds the preview by interpolating the unfurled metadata
into an HTML string. The image URL went into src="..." unescaped, so a
page whose og:image carries a double quote closes the attribute early and
everything after it becomes attributes on the preview's img element.

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 16:00:07 +02:00
committed by Rosa Gutierrez
parent ef147d17db
commit c1ad057db8
4 changed files with 134 additions and 4 deletions
@@ -18,6 +18,18 @@ class UnfurlLinksControllerTest < ActionDispatch::IntegrationTest
assert_equal "desc..", json_response["description"]
end
test "create strips markup from the title and description" do
entity_encoded_image_tag = "&#x3c;&#x69;&#x6d;&#x67;&#x20;&#x73;&#x72;&#x63;&#x3d;&#x61;&#x20;&#x6f;&#x6e;&#x65;&#x72;&#x72;&#x6f;&#x72;&#x3d;&#x70;&#x72;&#x6f;&#x6d;&#x70;&#x74;&#x28;&#x31;&#x29;&#x3e;"
stub_successful_request title: "#{entity_encoded_image_tag}Hey!", description: "#{entity_encoded_image_tag}desc.."
post unfurl_link_url, params: { url: "https://www.example.com" }
assert_response :success
json_response = JSON.parse(response.body)
assert_equal "Hey!", json_response["title"]
assert_equal "desc..", json_response["description"]
end
test "create with missing opengraph meta tags" do
WebMock.stub_request(:get, "https://www.example.com/").to_return(status: 200, body: "<html><head></head></html>", headers: {})
@@ -49,10 +61,10 @@ class UnfurlLinksControllerTest < ActionDispatch::IntegrationTest
end
private
def stub_successful_request(url: "https://www.example.com/")
def stub_successful_request(url: "https://www.example.com/", title: "Hey!", description: "desc..")
WebMock.stub_request(:get, url).to_return(
status: 200,
body: "<html><head><meta property=\"og:url\" content=\"https://example.com\"><meta property=\"og:title\" content=\"Hey!\"><meta property=\"og:description\" content=\"desc..\"><meta property=\"og:image\" content=\"https://example.com/image.png\"></head></html>",
body: "<html><head><meta property=\"og:url\" content=\"https://example.com\"><meta property=\"og:title\" content=\"#{title}\"><meta property=\"og:description\" content=\"#{description}\"><meta property=\"og:image\" content=\"https://example.com/image.png\"></head></html>",
headers: { content_type: "text/html" }
)