Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 92f122c

Browse files
authored
SECURITY: Fix XSS on Shared AI Conversations local Onebox (#1069)
1 parent cd03874 commit 92f122c

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed

app/models/shared_ai_conversation.rb

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,7 @@ def url
8888
def html_excerpt
8989
html = +""
9090
populated_context.each do |post|
91-
text =
92-
PrettyText.excerpt(
93-
post.cooked,
94-
400,
95-
text_entities: true,
96-
strip_links: true,
97-
strip_details: true,
98-
)
91+
text = PrettyText.excerpt(post.cooked, 400, strip_links: true, strip_details: true)
9992

10093
html << "<p><b>#{post.user.username}</b>: #{text}</p>"
10194
if html.length > 1000
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
class RebakeSharedAiConversationOneboxes < ActiveRecord::Migration[7.2]
3+
def up
4+
# Safe marking for rebake using raw SQL
5+
DB.exec(<<~SQL)
6+
UPDATE posts
7+
SET baked_version = NULL
8+
WHERE raw LIKE '%/discourse-ai/ai-bot/shared-ai-conversations/%';
9+
SQL
10+
end
11+
12+
def down
13+
raise ActiveRecord::IrreversibleMigration
14+
end
15+
end

spec/models/shared_ai_conversation_spec.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@
1313

1414
fab!(:user)
1515

16+
let(:bad_user_input) { <<~HTML }
17+
Just trying something `<marquee style="font-size: 200px; color: red;" scrollamount=20>h4cked</marquee>`
18+
HTML
1619
let(:raw_with_details) { <<~HTML }
1720
<details>
1821
<summary>GitHub pull request diff</summary>
1922
<p><a href="https://github.com/discourse/discourse-ai/pull/521">discourse/discourse-ai 521</a></p>
2023
</details>
2124
<p>This is some other text</p>
22-
HTML
25+
HTML
2326

2427
let(:bot_user) { claude_2.reload.user }
2528
let!(:topic) { Fabricate(:private_message_topic, recipient: bot_user) }
26-
let!(:post1) { Fabricate(:post, topic: topic, post_number: 1) }
29+
let!(:post1) { Fabricate(:post, topic: topic, post_number: 1, raw: bad_user_input) }
2730
let!(:post2) { Fabricate(:post, topic: topic, post_number: 2, raw: raw_with_details) }
2831

2932
describe ".share_conversation" do
@@ -70,5 +73,12 @@
7073
expect(populated_context[1].id).to eq(post2.id)
7174
expect(populated_context[1].user.id).to eq(post2.user.id)
7275
end
76+
77+
it "escapes HTML" do
78+
conversation = described_class.share_conversation(user, topic)
79+
onebox = conversation.onebox
80+
expect(onebox).not_to include("</marquee>")
81+
expect(onebox).to include("AI Conversation with Claude-2")
82+
end
7383
end
7484
end

0 commit comments

Comments
 (0)