diff options
author | Felipe Artur <felipefac@gmail.com> | 2016-05-09 19:35:37 -0300 |
---|---|---|
committer | Felipe Artur <felipefac@gmail.com> | 2016-05-09 19:35:37 -0300 |
commit | e56e3cdc62f96541b9bd8b7814204e92f1909253 (patch) | |
tree | fc3872d2ba8c02ae552fc583cbdbb163d3340b20 | |
parent | ae25c19ee5dcfae8ea977b2014657ecc6c3eaf3d (diff) | |
download | gitlab-ce-e56e3cdc62f96541b9bd8b7814204e92f1909253.tar.gz |
Fix api leaking notes when user is not authorized to read noteable
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | lib/api/notes.rb | 31 | ||||
-rw-r--r-- | spec/requests/api/notes_spec.rb | 19 |
3 files changed, 38 insertions, 13 deletions
diff --git a/CHANGELOG b/CHANGELOG index 63077523aaa..2c44944f66b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,7 @@ v 8.8.0 (unreleased) - Bump mail_room to 0.7.0 to fix stuck IDLE connections - Remove future dates from contribution calendar graph. - 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 - 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 diff --git a/lib/api/notes.rb b/lib/api/notes.rb index 71a53e6f0d6..4ac08a3e8c4 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -20,19 +20,24 @@ module API # GET /projects/:id/snippets/:noteable_id/notes get ":id/#{noteables_str}/:#{noteable_id_str}/notes" do @noteable = user_project.send(:"#{noteables_str}").find(params[:"#{noteable_id_str}"]) - - # 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 - # at the DB query level (which we cannot in that case), the current - # page can have less elements than :per_page even if - # there's more than one page. - notes = - # paginate() only works with a relation. This could lead to a - # mismatch between the pagination headers info and the actual notes - # array returned, but this is really a edge-case. - paginate(@noteable.notes). - reject { |n| n.cross_reference_not_visible_for?(current_user) } - present notes, with: Entities::Note + read_ability_name = "read_#{@noteable.class.to_s.underscore.downcase}".to_sym + + if can?(current_user, read_ability_name, @noteable) + # 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 + # at the DB query level (which we cannot in that case), the current + # page can have less elements than :per_page even if + # there's more than one page. + notes = + # paginate() only works with a relation. This could lead to a + # mismatch between the pagination headers info and the actual notes + # array returned, but this is really a edge-case. + 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 # Get a single +noteable+ note diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 49091fc0f49..f5b31be1ba3 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -57,6 +57,15 @@ describe API::API, api: true do expect(json_response).to be_empty 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 it "should return an empty array" do get api("/projects/#{ext_proj.id}/issues/#{ext_issue.id}/notes", private_user) @@ -80,6 +89,11 @@ describe API::API, api: true do get api("/projects/#{project.id}/snippets/42/notes", user) expect(response.status).to eq(404) 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 context "when noteable is a Merge Request" do @@ -94,6 +108,11 @@ describe API::API, api: true do get api("/projects/#{project.id}/merge_requests/4444/notes", user) expect(response.status).to eq(404) 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 |