SECURITY: Fix XSS on Shared AI Conversations local Onebox (#1069)
This commit is contained in:
parent
cd03874b4d
commit
92f122c54d
|
@ -88,14 +88,7 @@ class SharedAiConversation < ActiveRecord::Base
|
||||||
def html_excerpt
|
def html_excerpt
|
||||||
html = +""
|
html = +""
|
||||||
populated_context.each do |post|
|
populated_context.each do |post|
|
||||||
text =
|
text = PrettyText.excerpt(post.cooked, 400, strip_links: true, strip_details: true)
|
||||||
PrettyText.excerpt(
|
|
||||||
post.cooked,
|
|
||||||
400,
|
|
||||||
text_entities: true,
|
|
||||||
strip_links: true,
|
|
||||||
strip_details: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
html << "<p><b>#{post.user.username}</b>: #{text}</p>"
|
html << "<p><b>#{post.user.username}</b>: #{text}</p>"
|
||||||
if html.length > 1000
|
if html.length > 1000
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
class RebakeSharedAiConversationOneboxes < ActiveRecord::Migration[7.2]
|
||||||
|
def up
|
||||||
|
# Safe marking for rebake using raw SQL
|
||||||
|
DB.exec(<<~SQL)
|
||||||
|
UPDATE posts
|
||||||
|
SET baked_version = NULL
|
||||||
|
WHERE raw LIKE '%/discourse-ai/ai-bot/shared-ai-conversations/%';
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
raise ActiveRecord::IrreversibleMigration
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,6 +13,9 @@ RSpec.describe SharedAiConversation, type: :model do
|
||||||
|
|
||||||
fab!(:user)
|
fab!(:user)
|
||||||
|
|
||||||
|
let(:bad_user_input) { <<~HTML }
|
||||||
|
Just trying something `<marquee style="font-size: 200px; color: red;" scrollamount=20>h4cked</marquee>`
|
||||||
|
HTML
|
||||||
let(:raw_with_details) { <<~HTML }
|
let(:raw_with_details) { <<~HTML }
|
||||||
<details>
|
<details>
|
||||||
<summary>GitHub pull request diff</summary>
|
<summary>GitHub pull request diff</summary>
|
||||||
|
@ -23,7 +26,7 @@ RSpec.describe SharedAiConversation, type: :model do
|
||||||
|
|
||||||
let(:bot_user) { claude_2.reload.user }
|
let(:bot_user) { claude_2.reload.user }
|
||||||
let!(:topic) { Fabricate(:private_message_topic, recipient: bot_user) }
|
let!(:topic) { Fabricate(:private_message_topic, recipient: bot_user) }
|
||||||
let!(:post1) { Fabricate(:post, topic: topic, post_number: 1) }
|
let!(:post1) { Fabricate(:post, topic: topic, post_number: 1, raw: bad_user_input) }
|
||||||
let!(:post2) { Fabricate(:post, topic: topic, post_number: 2, raw: raw_with_details) }
|
let!(:post2) { Fabricate(:post, topic: topic, post_number: 2, raw: raw_with_details) }
|
||||||
|
|
||||||
describe ".share_conversation" do
|
describe ".share_conversation" do
|
||||||
|
@ -70,5 +73,12 @@ RSpec.describe SharedAiConversation, type: :model do
|
||||||
expect(populated_context[1].id).to eq(post2.id)
|
expect(populated_context[1].id).to eq(post2.id)
|
||||||
expect(populated_context[1].user.id).to eq(post2.user.id)
|
expect(populated_context[1].user.id).to eq(post2.user.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "escapes HTML" do
|
||||||
|
conversation = described_class.share_conversation(user, topic)
|
||||||
|
onebox = conversation.onebox
|
||||||
|
expect(onebox).not_to include("</marquee>")
|
||||||
|
expect(onebox).to include("AI Conversation with Claude-2")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue