Commit e56e3cdc authored by Felipe Artur's avatar Felipe Artur

Fix api leaking notes when user is not authorized to read noteable

parent ae25c19e
...@@ -15,6 +15,7 @@ v 8.8.0 (unreleased) ...@@ -15,6 +15,7 @@ v 8.8.0 (unreleased)
- Bump mail_room to 0.7.0 to fix stuck IDLE connections - Bump mail_room to 0.7.0 to fix stuck IDLE connections
- Remove future dates from contribution calendar graph. - Remove future dates from contribution calendar graph.
- Support e-mail notifications for comments on project snippets - Support e-mail notifications for comments on project snippets
- Fix API leak of notes of unauthorized issues, snippets and merge requests
- Use ActionDispatch Remote IP for Akismet checking - Use ActionDispatch Remote IP for Akismet checking
- Fix error when visiting commit builds page before build was updated - Fix error when visiting commit builds page before build was updated
- Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project - Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project
......
...@@ -20,19 +20,24 @@ module API ...@@ -20,19 +20,24 @@ module API
# GET /projects/:id/snippets/:noteable_id/notes # GET /projects/:id/snippets/:noteable_id/notes
get ":id/#{noteables_str}/:#{noteable_id_str}/notes" do get ":id/#{noteables_str}/:#{noteable_id_str}/notes" do
@noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"])
read_ability_name = "read_#{@noteable.class.to_s.underscore.downcase}".to_sym
# We exclude notes that are cross-references and that cannot be viewed
# by the current user. By doing this exclusion at this level and not if can?(current_user, read_ability_name, @noteable)
# at the DB query level (which we cannot in that case), the current # We exclude notes that are cross-references and that cannot be viewed
# page can have less elements than :per_page even if # by the current user. By doing this exclusion at this level and not
# there's more than one page. # at the DB query level (which we cannot in that case), the current
notes = # page can have less elements than :per_page even if
# paginate() only works with a relation. This could lead to a # there's more than one page.
# mismatch between the pagination headers info and the actual notes notes =
# array returned, but this is really a edge-case. # paginate() only works with a relation. This could lead to a
paginate(@noteable.notes). # mismatch between the pagination headers info and the actual notes
reject { |n| n.cross_reference_not_visible_for?(current_user) } # array returned, but this is really a edge-case.
present notes, with: Entities::Note paginate(@noteable.notes).
reject { |n| n.cross_reference_not_visible_for?(current_user) }
present notes, with: Entities::Note
else
render_api_error!("Not found.", 404)
end
end end
# Get a single +noteable+ note # Get a single +noteable+ note
......
...@@ -57,6 +57,15 @@ describe API::API, api: true do ...@@ -57,6 +57,15 @@ describe API::API, api: true do
expect(json_response).to be_empty expect(json_response).to be_empty
end end
context "and issue is confidential" do
before { ext_issue.update_attributes(confidential: true) }
it "returns 404" do
get api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes", user)
expect(response.status).to eq(404)
end
end
context "and current user can view the note" do context "and current user can view the note" do
it "should return an empty array" do it "should return an empty array" do
get api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes", private_user) get api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes", private_user)
...@@ -80,6 +89,11 @@ describe API::API, api: true do ...@@ -80,6 +89,11 @@ describe API::API, api: true do
get api("/projects/#{project.id}/snippets/42/notes", user) get api("/projects/#{project.id}/snippets/42/notes", user)
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
it "returns 404 when not authorized" do
get api("/projects/#{project.id}/snippets/#{snippet.id}/notes", private_user)
expect(response.status).to eq(404)
end
end end
context "when noteable is a Merge Request" do context "when noteable is a Merge Request" do
...@@ -94,6 +108,11 @@ describe API::API, api: true do ...@@ -94,6 +108,11 @@ describe API::API, api: true do
get api("/projects/#{project.id}/merge_requests/4444/notes", user) get api("/projects/#{project.id}/merge_requests/4444/notes", user)
expect(response.status).to eq(404) expect(response.status).to eq(404)
end end
it "returns 404 when not authorized" do
get api("/projects/#{project.id}/merge_requests/4444/notes", private_user)
expect(response.status).to eq(404)
end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment