0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 17:53:55 +08:00
discourse/spec/system/topic_embed_spec.rb
Mark VanLandingham 9e3cac68a6
SECURITY: Escape embed URL for HTML attribute context in footer (#42314)
## Summary

TopicEmbed.imported_from_html interpolated a URL-normalized value
directly into a single-quoted href attribute and display text. URL
normalization preserves apostrophes, allowing a crafted embed URL to
inject an HTML event-handler attribute into the companion footer. The
fix applies HTML escaping after URL normalization, preventing the value
from breaking out of its attribute or text contexts. Both the import and
expand embed paths are covered because they share the same generated
footer.

## Source

- Patch Triage: https://patch.discourse.org/patch-triage/1544
2026-08-04 09:59:30 -05:00

31 lines
1 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe "Imported topic embeds" do
fab!(:embeddable_host) { Fabricate(:embeddable_host, host: "eviltrout.com") }
let(:embed_url) { "http://eviltrout.com/'onmouseover='window.topicEmbedXssExecuted=true" }
before do
SiteSetting.content_security_policy = false
SiteSetting.import_embed_unlisted = false
Jobs.run_immediately!
stub_request(:get, embed_url).to_return(
status: 200,
body: "<html><title>Embedded article</title><body><p>Article content</p></body></html>",
)
end
it "does not execute JavaScript from an imported URL" do
visit("/embed/comments?#{{ embed_url: embed_url }.to_query}")
expect(page).to have_content(I18n.t("embed.loading"))
visit(TopicEmbed.last.post.topic.url)
link = find("#post_1 .cooked a", text: embed_url)
page.execute_script("window.topicEmbedXssExecuted = false")
link.hover
expect(page.evaluate_script("window.topicEmbedXssExecuted")).to eq(false)
expect(link["onmouseover"]).to be_nil
end
end