diff --git a/doc/user/application_security/sast/gitlab_advanced_sast.md b/doc/user/application_security/sast/gitlab_advanced_sast.md index 07b168f6e9ee0b75a60581cad9848b686b398fe3..8e222533eaf8a01cab3b61a1a19f43378318b891 100644 --- a/doc/user/application_security/sast/gitlab_advanced_sast.md +++ b/doc/user/application_security/sast/gitlab_advanced_sast.md @@ -147,15 +147,10 @@ When analyzing PHP code, GitLab Advanced SAST has the following limitations: - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/16790) in GitLab 18.5 [with a flag](../../../administration/feature_flags/_index.md) named `vulnerability_partial_scans`. Disabled by default. - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/552051) in GitLab 18.5. +- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/552051) in GitLab 18.6. Feature flag `vulnerability_partial_scans` removed. {{< /history >}} -{{< alert type="flag" >}} - -The availability of this feature is controlled by a feature flag. For more information, see the history. - -{{< /alert >}} - Diff-based scanning analyzes only the files modified in a merge request, along with their dependent files. This targeted approach reduces scan times and delivers faster feedback during development. To ensure complete coverage, a full scan runs on the default branch after the merge request is merged. @@ -163,7 +158,7 @@ To ensure complete coverage, a full scan runs on the default branch after the me When diff-based scanning is enabled: - Only files that were modified or added in the merge request, along with their dependent files, are scanned in merge request pipelines. -- If enabled, you’ll see the job log print: `Running differential scan` +- If enabled, you'll see the job log print: `Running differential scan` If disabled, it prints: `Running full scan` - In the **merge request security widget**, a dedicated **Diff-based** tab shows relevant scan findings. - In the **Pipeline Security** tab, an alert labeled **Partial SAST report** indicates that only partial findings are included. diff --git a/ee/app/assets/javascripts/security_dashboard/components/pipeline/pipeline_vulnerability_report.vue b/ee/app/assets/javascripts/security_dashboard/components/pipeline/pipeline_vulnerability_report.vue index 4a9f2984e59870e7d1b15a9279718c56bc4ab48c..2c084798bd4d00d870248c4bfac465f2ae4e44e6 100644 --- a/ee/app/assets/javascripts/security_dashboard/components/pipeline/pipeline_vulnerability_report.vue +++ b/ee/app/assets/javascripts/security_dashboard/components/pipeline/pipeline_vulnerability_report.vue @@ -63,9 +63,6 @@ export default { message: s__('ciReport|Error while fetching enabled scans. Please try again later.'), }); }, - skip() { - return !this.glFeatures.vulnerabilityPartialScans; - }, }, }, diff --git a/ee/app/assets/javascripts/vue_merge_request_widget/widgets/security_reports/mr_widget_security_reports.vue b/ee/app/assets/javascripts/vue_merge_request_widget/widgets/security_reports/mr_widget_security_reports.vue index c7cc42dd24dc5981865ad1863844d98d6cfe1725..5e3b0a08a3f98abe644b7e50b2a0078f5dfa607b 100644 --- a/ee/app/assets/javascripts/vue_merge_request_widget/widgets/security_reports/mr_widget_security_reports.vue +++ b/ee/app/assets/javascripts/vue_merge_request_widget/widgets/security_reports/mr_widget_security_reports.vue @@ -6,7 +6,6 @@ import axios from '~/lib/utils/axios_utils'; import { s__ } from '~/locale'; import enabledScansQuery from 'ee/vue_merge_request_widget/queries/enabled_scans.query.graphql'; import SummaryHighlights from 'ee/vue_shared/security_reports/components/summary_highlights.vue'; -import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants'; import { convertToCamelCase } from '~/lib/utils/text_utility'; import { helpPagePath } from '~/helpers/help_page_helper'; @@ -31,7 +30,6 @@ export default { SummaryHighlights, SecurityTrainingPromoWidget, }, - mixins: [glFeatureFlagMixin()], i18n, props: { mr: { @@ -253,10 +251,6 @@ export default { ); }, skip() { - if (!this.glFeatures.vulnerabilityPartialScans) { - return true; - } - return ( !this.mr.pipeline?.iid || !this.mr.targetProjectFullPath || diff --git a/ee/app/controllers/ee/projects/merge_requests_controller.rb b/ee/app/controllers/ee/projects/merge_requests_controller.rb index a6c95bc43c5f8f7588a1661d6ed317ae6f08b05e..256e6d19ca9a547c34d57d3713ea332b345f4a46 100644 --- a/ee/app/controllers/ee/projects/merge_requests_controller.rb +++ b/ee/app/controllers/ee/projects/merge_requests_controller.rb @@ -11,7 +11,6 @@ module MergeRequestsController before_action only: [:show] do push_frontend_feature_flag(:merge_trains_skip_train, @project) - push_frontend_feature_flag(:vulnerability_partial_scans, @project) push_frontend_feature_flag(:security_policy_approval_warn_mode, @project) push_frontend_ability(ability: :resolve_vulnerability_with_ai, resource: @project, user: current_user) push_frontend_ability(ability: :measure_comment_temperature, resource: merge_request, user: current_user) diff --git a/ee/app/controllers/ee/projects/pipelines_controller.rb b/ee/app/controllers/ee/projects/pipelines_controller.rb index bbb1549434f3aef72f306342fa49da292f848eca..263871cb0f983fc0fa44bc607d0777ae8afa5236 100644 --- a/ee/app/controllers/ee/projects/pipelines_controller.rb +++ b/ee/app/controllers/ee/projects/pipelines_controller.rb @@ -11,7 +11,6 @@ module PipelinesController before_action :authorize_read_licenses!, only: [:licenses, :license_count] before_action do - push_frontend_feature_flag(:vulnerability_partial_scans, project) push_frontend_feature_flag(:vulnerability_report_type_scanner_filter) push_frontend_feature_flag(:validity_checks_security_finding_status, project) end diff --git a/ee/app/finders/security/findings_finder.rb b/ee/app/finders/security/findings_finder.rb index 01fb0986415ca92cc28a23249acce0b8cefc2ed9..c77a339101d38e498d195a024d397009a6907e82 100644 --- a/ee/app/finders/security/findings_finder.rb +++ b/ee/app/finders/security/findings_finder.rb @@ -143,7 +143,7 @@ def by_report_types(relation) def by_scan_mode(relation) scan_mode = params.fetch(:scan_mode, 'all') - return relation if ::Feature.disabled?(:vulnerability_partial_scans, project) || scan_mode == 'all' + return relation if scan_mode == 'all' exists_clause = <<~SQL EXISTS ( diff --git a/ee/app/services/security/merge_request_security_report_generation_service.rb b/ee/app/services/security/merge_request_security_report_generation_service.rb index 57836b69dfbe6007faf413a845a19b771b1d3a32..5167a3f9a45ecd5ee8700393f75bed6fae65a8d7 100644 --- a/ee/app/services/security/merge_request_security_report_generation_service.rb +++ b/ee/app/services/security/merge_request_security_report_generation_service.rb @@ -106,8 +106,6 @@ def fixed_findings strong_memoize_attr def report validate_report_type! - return old_report if Feature.disabled?(:vulnerability_partial_scans, project) - with_reactive_cache(params.stringify_keys) do |data| latest = Vulnerabilities::CompareSecurityReportsService.new(project, nil, params).latest?(base_pipeline, head_pipeline, data) @@ -117,25 +115,6 @@ def fixed_findings end || { status: :parsing } end - def old_report - case report_type - when 'sast' - merge_request.compare_sast_reports(nil) - when 'secret_detection' - merge_request.compare_secret_detection_reports(nil) - when 'container_scanning' - merge_request.compare_container_scanning_reports(nil) - when 'dependency_scanning' - merge_request.compare_dependency_scanning_reports(nil) - when 'dast' - merge_request.compare_dast_reports(nil) - when 'coverage_fuzzing' - merge_request.compare_coverage_fuzzing_reports(nil) - when 'api_fuzzing' - merge_request.compare_api_fuzzing_reports(nil) - end - end - def validate_report_type! raise InvalidReportTypeError unless ALLOWED_REPORT_TYPES.include?(report_type) end diff --git a/ee/app/services/security/store_scan_service.rb b/ee/app/services/security/store_scan_service.rb index 4e53f11374556dd8b984da52f19a3a668e51306d..332c4a68ea197dc820885d416c92081125e720fa 100644 --- a/ee/app/services/security/store_scan_service.rb +++ b/ee/app/services/security/store_scan_service.rb @@ -77,8 +77,6 @@ def security_scan alias_method :store_security_scan, :security_scan def store_partial_scan - return unless ::Feature.enabled?(:vulnerability_partial_scans, project) - # If we have a dependency scanning report then `scan` will return nil mode = security_report.scan&.partial_scan_mode diff --git a/ee/config/feature_flags/beta/vulnerability_partial_scans.yml b/ee/config/feature_flags/beta/vulnerability_partial_scans.yml deleted file mode 100644 index 4f767d9b43cc89d0f2bcbb0bb4256f6745709819..0000000000000000000000000000000000000000 --- a/ee/config/feature_flags/beta/vulnerability_partial_scans.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: vulnerability_partial_scans -description: Track scans that do not run on the entire codebase and indicate them on the MR -feature_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/17758 -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/195373 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/552051 -milestone: '18.2' -group: group::security insights -type: beta -default_enabled: true diff --git a/ee/spec/finders/security/findings_finder_spec.rb b/ee/spec/finders/security/findings_finder_spec.rb index c2f6d82afab478d7b93982e96ade2beaf11b60a8..0793c858313efb93bb59fb5b226fcc1e91544e1a 100644 --- a/ee/spec/finders/security/findings_finder_spec.rb +++ b/ee/spec/finders/security/findings_finder_spec.rb @@ -310,18 +310,6 @@ it 'returns only full scan results' do is_expected.to match_array(expected_uuids) end - - context 'when feature is disabled' do - before do - stub_feature_flags(vulnerability_partial_scans: false) - end - - let(:result_uuids) { Security::Finding.pluck(:uuid) } - - it 'returns both full and partial scan results' do - is_expected.to match_array(expected_uuids) - end - end end context 'when scan_mode is partial' do @@ -331,18 +319,6 @@ it 'returns only partial scan results' do is_expected.to match_array(expected_uuids) end - - context 'when feature is disabled' do - before do - stub_feature_flags(vulnerability_partial_scans: false) - end - - let(:result_uuids) { Security::Finding.pluck(:uuid) } - - it 'returns both full and partial scan results' do - is_expected.to match_array(expected_uuids) - end - end end end end diff --git a/ee/spec/frontend/security_dashboard/components/pipeline/pipeline_vulnerability_report_spec.js b/ee/spec/frontend/security_dashboard/components/pipeline/pipeline_vulnerability_report_spec.js index c55dae353ff00fddab0e3d90a64942a1a99ace4e..b55b690e8fbee8b83cd5a44cd3493a1153acd576 100644 --- a/ee/spec/frontend/security_dashboard/components/pipeline/pipeline_vulnerability_report_spec.js +++ b/ee/spec/frontend/security_dashboard/components/pipeline/pipeline_vulnerability_report_spec.js @@ -27,7 +27,6 @@ describe('Pipeline vulnerability report', () => { const createWrapper = ({ vulnerabilityReportTypeScannerFilter = true, - vulnerabilityPartialScans = false, mockApolloProvider, } = {}) => { wrapper = shallowMountExtended(PipelineVulnerabilityReport, { @@ -41,7 +40,6 @@ describe('Pipeline vulnerability report', () => { projectFullPath: TEST_PROJECT_FULL_PATH, glFeatures: { vulnerabilityReportTypeScannerFilter, - vulnerabilityPartialScans, }, }, }); @@ -203,7 +201,6 @@ describe('Pipeline vulnerability report', () => { it('should create an alert when enabled scans query fails', async () => { createWrapper({ - vulnerabilityPartialScans: true, mockApolloProvider: createMockApollo([ [enabledScansQuery, jest.fn().mockRejectedValue({})], ]), @@ -224,7 +221,6 @@ describe('Pipeline vulnerability report', () => { 'should $text the banner when partial scans are enabled=$hasBanner', async ({ enabledPartialScans, hasBanner }) => { createWrapper({ - vulnerabilityPartialScans: true, mockApolloProvider: createMockApollo([ [ enabledScansQuery, diff --git a/ee/spec/frontend/vue_merge_request_widget/widgets/security_reports/mr_widget_security_reports_spec.js b/ee/spec/frontend/vue_merge_request_widget/widgets/security_reports/mr_widget_security_reports_spec.js index ec1b4f2a9c42615ef6b5b312bebbc346c07bbf0b..14c149307ed043b6033589c9dd859625f49c15bb 100644 --- a/ee/spec/frontend/vue_merge_request_widget/widgets/security_reports/mr_widget_security_reports_spec.js +++ b/ee/spec/frontend/vue_merge_request_widget/widgets/security_reports/mr_widget_security_reports_spec.js @@ -163,6 +163,19 @@ describe('MR Widget Security Reports', () => { propsData: { mr: mrProps, }, + mockApolloProvider: createMockApollo([ + [ + enabledScansQuery, + jest.fn().mockResolvedValue( + enabledScansQueryResult({ + full: { + sast: true, + dast: true, + }, + }), + ), + ], + ]), ...options, }); @@ -213,10 +226,9 @@ describe('MR Widget Security Reports', () => { }); }); - describe('with vulnerabilityPartialScans feature flag turned on', () => { + describe('partial scans', () => { it('should display a loading state until enabled scans are fetched', async () => { createComponent({ - provide: { glFeatures: { vulnerabilityPartialScans: true } }, mountFn: mountExtended, mockApolloProvider: defaultMockApollo, }); @@ -236,7 +248,6 @@ describe('MR Widget Security Reports', () => { 'should fetch full scans=$fullScans, partial scans=$partialScans', async ({ fullScans, partialScans, expectedNumberOfRESTcalls, expectedScanModes }) => { createComponent({ - provide: { glFeatures: { vulnerabilityPartialScans: true } }, mountFn: mountExtended, mockApolloProvider: createMockApollo([ [ @@ -272,7 +283,6 @@ describe('MR Widget Security Reports', () => { mockAxios = new MockAdapter(axios); createComponent({ - provide: { glFeatures: { vulnerabilityPartialScans: true } }, mountFn: mountExtended, apolloProvider: createMockApollo([ [ @@ -317,7 +327,6 @@ describe('MR Widget Security Reports', () => { it('when the query fails', async () => { createComponent({ - provide: { glFeatures: { vulnerabilityPartialScans: true } }, mountFn: mountExtended, apolloProvider: createMockApollo([ [ @@ -338,7 +347,6 @@ describe('MR Widget Security Reports', () => { it('when the pipeline is null, it should not render anything', async () => { createComponent({ - provide: { glFeatures: { vulnerabilityPartialScans: true } }, mountFn: mountExtended, apolloProvider: createMockApollo([ [ @@ -363,7 +371,7 @@ describe('MR Widget Security Reports', () => { describe('with empty MR data', () => { beforeEach(() => { - createComponent(); + createComponent({ mockApolloProvider: defaultMockApollo }); }); it('should mount the widget component', () => { @@ -446,6 +454,19 @@ describe('MR Widget Security Reports', () => { createComponent({ mountFn: mountExtended, + mockApolloProvider: createMockApollo([ + [ + enabledScansQuery, + jest.fn().mockResolvedValue( + enabledScansQueryResult({ + full: { + sast: true, + dast: true, + }, + }), + ), + ], + ]), }); await waitForPromises(); @@ -472,7 +493,7 @@ describe('MR Widget Security Reports', () => { }); it('should display the view all pipeline findings button', async () => { - await createComponent(); + await createComponent({ mockApolloProvider: defaultMockApollo }); expect(findWidget().props('actionButtons')).toEqual([ { diff --git a/ee/spec/services/security/merge_request_security_report_generation_service_spec.rb b/ee/spec/services/security/merge_request_security_report_generation_service_spec.rb index bc636f3d4d59828cf4a73770d64b48ff17288c56..89019076f7d87ffc9f0d5b618b64234eef12c41c 100644 --- a/ee/spec/services/security/merge_request_security_report_generation_service_spec.rb +++ b/ee/spec/services/security/merge_request_security_report_generation_service_spec.rb @@ -226,18 +226,6 @@ def stub_report(data) } end - context 'when vulnerability_partial_scans is disabled' do - before do - stub_feature_flags(vulnerability_partial_scans: false) - end - - it 'returns the report and does not queue ReactiveCachingWorker' do - expect(ReactiveCachingWorker).not_to receive(:perform_async) - expect(merge_request).to receive(mr_report_method).with(nil).and_return(mock_report) - expect(report).to eq(expected_report) - end - end - context 'when cached results is not latest' do before do allow(ReactiveCachingWorker).to receive(:perform_async).and_call_original diff --git a/ee/spec/services/security/store_scan_service_spec.rb b/ee/spec/services/security/store_scan_service_spec.rb index 167ae425d1e4dbfc7ffcc5f00a9d740a9dff63f7..beaecc6001045f5503b826ab52263c1c3c9e8298 100644 --- a/ee/spec/services/security/store_scan_service_spec.rb +++ b/ee/spec/services/security/store_scan_service_spec.rb @@ -137,18 +137,6 @@ it_behaves_like 'stores partial scan record' - context 'when vulnerability_partial_scans feature flag is disabled' do - before do - stub_feature_flags(vulnerability_partial_scans: false) - end - - it 'does not create partial scan record' do - store_scan - - expect(security_scan.partial_scan).to be_nil - end - end - context 'when there is an existing security scan' do let_it_be(:existing_scan) do create(:security_scan, build: artifact.job, scan_type: artifact.security_report.type)