Commit 17a87c03 authored by Alex Kalderimis's avatar Alex Kalderimis

Fixes leak of number of vulnerabilities

Fixes https://gitlab.com/gitlab-org/gitlab/-/issues/219247
parent 4ee871cb
...@@ -3,8 +3,11 @@ ...@@ -3,8 +3,11 @@
module Resolvers module Resolvers
class VulnerabilitySeveritiesCountResolver < VulnerabilitiesBaseResolver class VulnerabilitySeveritiesCountResolver < VulnerabilitiesBaseResolver
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
include Gitlab::Graphql::Authorize::AuthorizeResource
type Types::VulnerabilitySeveritiesCountType, null: true type Types::VulnerabilitySeveritiesCountType, null: true
authorize :read_vulnerability
authorizes_object!
argument :project_id, [GraphQL::ID_TYPE], argument :project_id, [GraphQL::ID_TYPE],
required: false, required: false,
......
...@@ -282,7 +282,10 @@ module EE ...@@ -282,7 +282,10 @@ module EE
rule { security_dashboard_enabled & developer }.enable :read_group_security_dashboard rule { security_dashboard_enabled & developer }.enable :read_group_security_dashboard
rule { can?(:read_group_security_dashboard) }.enable :create_vulnerability_export rule { can?(:read_group_security_dashboard) }.policy do
enable :create_vulnerability_export
enable :read_vulnerability
end
rule { admin | owner }.policy do rule { admin | owner }.policy do
enable :read_group_compliance_dashboard enable :read_group_compliance_dashboard
......
...@@ -6,6 +6,10 @@ class InstanceSecurityDashboardPolicy < BasePolicy ...@@ -6,6 +6,10 @@ class InstanceSecurityDashboardPolicy < BasePolicy
License.feature_available?(:security_dashboard) License.feature_available?(:security_dashboard)
end end
rule { ~anonymous }.enable :read_instance_security_dashboard rule { ~anonymous }.policy do
enable :read_instance_security_dashboard
enable :read_vulnerability
end
rule { security_dashboard_enabled & can?(:read_instance_security_dashboard) }.enable :create_vulnerability_export rule { security_dashboard_enabled & can?(:read_instance_security_dashboard) }.enable :create_vulnerability_export
end end
---
title: Require permissions to read vulnerability counts
merge_request: 57037
author:
type: fixed
...@@ -27,50 +27,64 @@ RSpec.describe Resolvers::VulnerabilitySeveritiesCountResolver do ...@@ -27,50 +27,64 @@ RSpec.describe Resolvers::VulnerabilitySeveritiesCountResolver do
let(:filters) { {} } let(:filters) { {} }
let(:vulnerable) { project } let(:vulnerable) { project }
context 'when given severities' do context 'when the user does not have access' do
let(:filters) { { severity: ['low'] } } it 'is redacted' do
is_expected.to be_nil
it 'only returns count for low severity vulnerability' do
is_expected.to eq('low' => 1)
end end
end end
context 'when given states' do context 'when the user has access' do
let(:filters) { { state: ['dismissed'] } } before do
stub_licensed_features(security_dashboard: true)
project.add_developer(current_user)
end
context 'when given severities' do
let(:filters) { { severity: ['low'] } }
it 'only returns count for high severity vulnerability' do it 'only returns count for low severity vulnerability' do
is_expected.to eq('high' => 1) is_expected.to eq('low' => 1)
end
end end
end
context 'when given scanner' do context 'when given states' do
let(:filters) { { scanner: [high_vulnerability.finding_scanner_external_id] } } let(:filters) { { state: ['dismissed'] } }
it 'only returns count for high severity vulnerability' do it 'only returns count for high severity vulnerability' do
is_expected.to eq('high' => 1) is_expected.to eq('high' => 1)
end
end end
end
context 'when given report types' do context 'when given scanner' do
let(:filters) { { report_type: %i[dast sast] } } let(:filters) { { scanner: [high_vulnerability.finding_scanner_external_id] } }
it 'only returns count for vulnerabilities of the given report types' do it 'only returns count for high severity vulnerability' do
is_expected.to eq('critical' => 1, 'low' => 1) is_expected.to eq('high' => 1)
end
end
context 'when given report types' do
let(:filters) { { report_type: %i[dast sast] } }
it 'only returns count for vulnerabilities of the given report types' do
is_expected.to eq('critical' => 1, 'low' => 1)
end
end end
end
context 'when resolving vulnerabilities for a project' do context 'when resolving vulnerabilities for a project' do
it "returns the project's vulnerabilities" do it "returns the project's vulnerabilities" do
is_expected.to eq('critical' => 1, 'high' => 1, 'low' => 1) is_expected.to eq('critical' => 1, 'high' => 1, 'low' => 1)
end
end end
end end
context 'when resolving vulnerabilities for an instance security dashboard' do context 'when resolving vulnerabilities for an instance security dashboard' do
before do before do
stub_licensed_features(security_dashboard: true)
project.add_developer(user) project.add_developer(user)
end end
let(:vulnerable) { nil } let(:vulnerable) { InstanceSecurityDashboard.new(current_user) }
context 'when there is a current user' do context 'when there is a current user' do
it "returns vulnerabilities for all projects on the current user's instance security dashboard" do it "returns vulnerabilities for all projects on the current user's instance security dashboard" do
...@@ -78,11 +92,11 @@ RSpec.describe Resolvers::VulnerabilitySeveritiesCountResolver do ...@@ -78,11 +92,11 @@ RSpec.describe Resolvers::VulnerabilitySeveritiesCountResolver do
end end
end end
context 'and there is no current user' do context 'without a current user' do
let(:current_user) { nil } let(:current_user) { nil }
it 'returns no vulnerabilities' do it 'returns no vulnerabilities' do
is_expected.to be_empty is_expected.to be_blank
end end
end end
end end
......
...@@ -846,7 +846,9 @@ RSpec.describe GroupPolicy do ...@@ -846,7 +846,9 @@ RSpec.describe GroupPolicy do
end end
describe 'read_group_security_dashboard & create_vulnerability_export' do describe 'read_group_security_dashboard & create_vulnerability_export' do
let(:abilities) { %i(read_group_security_dashboard create_vulnerability_export) } let(:abilities) do
%i[read_group_security_dashboard create_vulnerability_export read_vulnerability]
end
before do before do
stub_licensed_features(security_dashboard: true) stub_licensed_features(security_dashboard: true)
......
...@@ -13,14 +13,16 @@ RSpec.describe InstanceSecurityDashboardPolicy do ...@@ -13,14 +13,16 @@ RSpec.describe InstanceSecurityDashboardPolicy do
subject { described_class.new(current_user, [user]) } subject { described_class.new(current_user, [user]) }
describe 'read_instance_security_dashboard' do describe 'read_instance_security_dashboard' do
let(:abilities) { %i[read_instance_security_dashboard read_vulnerability] }
context 'when the user is not logged in' do context 'when the user is not logged in' do
let(:current_user) { nil } let(:current_user) { nil }
it { is_expected.not_to be_allowed(:read_instance_security_dashboard) } it { is_expected.not_to be_allowed(*abilities) }
end end
context 'when the user is logged in' do context 'when the user is logged in' do
it { is_expected.to be_allowed(:read_instance_security_dashboard) } it { is_expected.to be_allowed(*abilities) }
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