0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-09 21:45:25 +08:00
discourse/spec/lib/guardian/upload_guardian_spec.rb
Alan Guo Xiang Tan eeaca70bc1
FIX: Enforce secure-upload ACL in AI bot prompt path (#39903)
The AI bot reads upload contents from posts and chat messages and feeds
them into the LLM prompt. The lookup is gated by whether the requester
can see the post, but not whether they can see the upload's secure
access-control post, so an attacker can paste another user's secure
short URL into their own post, summon the bot, and have it disclose the
contents. The agent tool runner's `_upload_get_base64` has the same gap
with no ACL check at all.

This commit introduces `Guardian#can_see_upload?` so upload visibility
is checked in one place, and uses it from `PromptMessagesBuilder`,
`ToolRunner::Upload`, and
`SecureUploadEndpointHelpers#check_secure_upload_permission`.

Follow-up to fa54f62348.
2026-05-13 09:55:32 +08:00

55 lines
1.8 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe UploadGuardian do
fab!(:user)
fab!(:public_post, :post)
fab!(:private_group, :group)
fab!(:private_category) { Fabricate(:private_category, group: private_group) }
fab!(:private_topic) { Fabricate(:topic, category: private_category) }
fab!(:private_post) { Fabricate(:post, topic: private_topic) }
fab!(:non_secure_upload_without_access_control_post) do
Fabricate(:upload, access_control_post: nil)
end
fab!(:secure_upload_without_access_control_post) do
Fabricate(:secure_upload, access_control_post: nil)
end
fab!(:upload_with_visible_access_control_post) do
Fabricate(:upload, access_control_post: public_post)
end
fab!(:secure_upload_with_hidden_access_control_post) do
Fabricate(:secure_upload, access_control_post: private_post)
end
describe "#can_see_upload?" do
it "returns true for a non-secure upload with no access_control_post" do
expect(
Guardian.new(user).can_see_upload?(non_secure_upload_without_access_control_post),
).to eq(true)
end
it "returns false for a secure upload with no access_control_post" do
expect(Guardian.new(user).can_see_upload?(secure_upload_without_access_control_post)).to eq(
false,
)
end
it "returns true for an upload whose access_control_post the user can see" do
expect(Guardian.new(user).can_see_upload?(upload_with_visible_access_control_post)).to eq(
true,
)
private_group.add(user)
expect(
Guardian.new(user).can_see_upload?(secure_upload_with_hidden_access_control_post),
).to eq(true)
end
it "returns false for an upload whose access_control_post the user cannot see" do
expect(
Guardian.new(user).can_see_upload?(secure_upload_with_hidden_access_control_post),
).to eq(false)
end
end
end