From 6510c81a177ea56e20775b1f356e664c64f12b26 Mon Sep 17 00:00:00 2001 From: Serena Fang <sfang@gitlab.com> Date: Fri, 13 Sep 2024 13:12:23 -0500 Subject: [PATCH 1/4] Check gitaly protocol for diff scanning Only scan diffs if http or ssh protocol. If web, scan entire file Changelog: changed --- ee/lib/gitlab/checks/secrets_check.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ee/lib/gitlab/checks/secrets_check.rb b/ee/lib/gitlab/checks/secrets_check.rb index 74c1b8e2fc6cc4..f012b3cb24503b 100644 --- a/ee/lib/gitlab/checks/secrets_check.rb +++ b/ee/lib/gitlab/checks/secrets_check.rb @@ -99,6 +99,14 @@ def validate! private + def http_or_ssh_protocol + changes_access.protocol == "http" || changes_access.protocol == "ssh" + end + + def use_diff_scan + Feature.enabled?(:spp_scan_diffs, project) && http_or_ssh_protocol + end + def run_pre_receive_secret_detection? Gitlab::CurrentSettings.current_application_settings.pre_receive_secret_detection_enabled && (enabled_for_non_dedicated_project? || enabled_for_dedicated_project?) -- GitLab From 4650a7dcb244a355365fa16e27b64c8d1e447c38 Mon Sep 17 00:00:00 2001 From: Serena Fang <sfang@gitlab.com> Date: Wed, 18 Sep 2024 19:00:07 -0500 Subject: [PATCH 2/4] Doc protocol differences --- .../secret_detection/secret_push_protection/index.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/user/application_security/secret_detection/secret_push_protection/index.md b/doc/user/application_security/secret_detection/secret_push_protection/index.md index 62b1f744802fd8..5e384c6fe668b5 100644 --- a/doc/user/application_security/secret_detection/secret_push_protection/index.md +++ b/doc/user/application_security/secret_detection/secret_push_protection/index.md @@ -117,6 +117,10 @@ This can cause a [push to be blocked unexpectedly](#push-blocked-unexpectedly) w You can enable the `spp_scan_diffs` [feature flag](../../../../administration/feature_flags.md) for your project, which modifies Secret Push Protection to only scan newly committed changes (or diffs), and not the rest of the file. +When `spp_scan_diffs` is enabled, Secret Push Protection scans the diffs for CLI-based pushes via HTTP/SSH. +Changes committed via the WebIDE still result in the entire file being scanned due to a technical limitation. +[Issue 491282](https://gitlab.com/gitlab-org/gitlab/-/issues/491282) addresses the limitation so only the diffs are scanned for WebIDE changes. + ## Resolve a blocked push When secret push protection blocks a push, you can either: @@ -210,6 +214,7 @@ Secret Push Protection scans all contents of modified files. This can cause a pu if a modified file contains a secret, even if the secret is not part of the diff. [Enable the `spp_scan_diffs` feature flag](#diff-scanning) to ensure that only newly committed changes are scanned. +To push a WebIDE change to a file that contains a secret, you need to [skip secret push protection](#skip-secret-push-protection). ### File was not scanned -- GitLab From d7ea47eba167cfcc1fcf10f8e4a217fda390c65b Mon Sep 17 00:00:00 2001 From: Serena Fang <sfang@gitlab.com> Date: Thu, 3 Oct 2024 01:06:12 -0500 Subject: [PATCH 3/4] Add specs, use use_diff_scan --- ee/lib/gitlab/checks/secrets_check.rb | 2 +- .../lib/gitlab/checks/secrets_check_spec.rb | 25 +++++++++++++++++++ .../gitlab/secrets_check_shared_examples.rb | 2 ++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/ee/lib/gitlab/checks/secrets_check.rb b/ee/lib/gitlab/checks/secrets_check.rb index f012b3cb24503b..e80467a1014ef8 100644 --- a/ee/lib/gitlab/checks/secrets_check.rb +++ b/ee/lib/gitlab/checks/secrets_check.rb @@ -68,7 +68,7 @@ def validate! end logger.log_timed(LOG_MESSAGES[:secrets_check]) do - if Feature.enabled?(:spp_scan_diffs, project) + if use_diff_scan payloads = get_diffs # Pass payloads to gem for scanning. response = ::Gitlab::SecretDetection::ScanDiffs diff --git a/ee/spec/lib/gitlab/checks/secrets_check_spec.rb b/ee/spec/lib/gitlab/checks/secrets_check_spec.rb index dd0ed5a964dc8c..3de864051dbd8e 100644 --- a/ee/spec/lib/gitlab/checks/secrets_check_spec.rb +++ b/ee/spec/lib/gitlab/checks/secrets_check_spec.rb @@ -67,6 +67,31 @@ it_behaves_like 'diff scan skipped when a commit has special bypass flag' it_behaves_like 'diff scan skipped when secret_push_protection.skip_all push option is passed' + context 'when the protocol is web' do + let(:changes_access_web) do + Gitlab::Checks::ChangesAccess.new( + changes, + project: project, + user_access: user_access, + protocol: 'web', + logger: logger, + push_options: push_options + ) + end + + subject(:secrets_check) { described_class.new(changes_access_web) } + + it_behaves_like 'scan passed' + it_behaves_like 'scan detected secrets' + it_behaves_like 'scan detected secrets but some errors occured' + it_behaves_like 'scan timed out' + it_behaves_like 'scan failed to initialize' + it_behaves_like 'scan failed with invalid input' + it_behaves_like 'scan skipped due to invalid status' + it_behaves_like 'scan skipped when a commit has special bypass flag' + it_behaves_like 'scan skipped when secret_push_protection.skip_all push option is passed' + end + context 'when the scan diff feature flag is not enabled' do before do stub_feature_flags(spp_scan_diffs: false) diff --git a/ee/spec/support/shared_examples/lib/gitlab/secrets_check_shared_examples.rb b/ee/spec/support/shared_examples/lib/gitlab/secrets_check_shared_examples.rb index c32ef179a65034..396e48f3674067 100644 --- a/ee/spec/support/shared_examples/lib/gitlab/secrets_check_shared_examples.rb +++ b/ee/spec/support/shared_examples/lib/gitlab/secrets_check_shared_examples.rb @@ -1136,6 +1136,8 @@ ) end + subject(:secrets_check) { described_class.new(changes_access) } + let_it_be(:new_commit) do create_commit( { '.env' => 'SECRET=glpat-JUST20LETTERSANDNUMB' } # gitleaks:allow -- GitLab From 15333566ea51be12cd42928ab4d7c79df7ca299f Mon Sep 17 00:00:00 2001 From: Serena Fang <sfang@gitlab.com> Date: Thu, 3 Oct 2024 10:18:58 -0500 Subject: [PATCH 4/4] Apply reviewer suggestions --- ee/lib/gitlab/checks/secrets_check.rb | 10 +-- .../lib/gitlab/checks/secrets_check_spec.rb | 71 ++++++++++--------- .../secrets_check_shared_contexts.rb | 11 +++ 3 files changed, 54 insertions(+), 38 deletions(-) diff --git a/ee/lib/gitlab/checks/secrets_check.rb b/ee/lib/gitlab/checks/secrets_check.rb index e80467a1014ef8..7c54afbcb96a91 100644 --- a/ee/lib/gitlab/checks/secrets_check.rb +++ b/ee/lib/gitlab/checks/secrets_check.rb @@ -68,7 +68,7 @@ def validate! end logger.log_timed(LOG_MESSAGES[:secrets_check]) do - if use_diff_scan + if use_diff_scan? payloads = get_diffs # Pass payloads to gem for scanning. response = ::Gitlab::SecretDetection::ScanDiffs @@ -99,12 +99,12 @@ def validate! private - def http_or_ssh_protocol - changes_access.protocol == "http" || changes_access.protocol == "ssh" + def http_or_ssh_protocol? + %w[http ssh].include?(changes_access.protocol) end - def use_diff_scan - Feature.enabled?(:spp_scan_diffs, project) && http_or_ssh_protocol + def use_diff_scan? + Feature.enabled?(:spp_scan_diffs, project) && http_or_ssh_protocol? end def run_pre_receive_secret_detection? diff --git a/ee/spec/lib/gitlab/checks/secrets_check_spec.rb b/ee/spec/lib/gitlab/checks/secrets_check_spec.rb index 3de864051dbd8e..00b19bf89527a1 100644 --- a/ee/spec/lib/gitlab/checks/secrets_check_spec.rb +++ b/ee/spec/lib/gitlab/checks/secrets_check_spec.rb @@ -56,40 +56,31 @@ it_behaves_like 'skips the push check' end - it_behaves_like 'diff scan passed' - it_behaves_like 'diff scan detected secrets' - it_behaves_like 'diff scan detected secrets but some errors occured' - it_behaves_like 'diff scan timed out' - it_behaves_like 'diff scan failed to initialize' - it_behaves_like 'diff scan failed with invalid input' - it_behaves_like 'diff scan handles malformed blobs' - it_behaves_like 'diff scan skipped due to invalid status' - it_behaves_like 'diff scan skipped when a commit has special bypass flag' - it_behaves_like 'diff scan skipped when secret_push_protection.skip_all push option is passed' - - context 'when the protocol is web' do - let(:changes_access_web) do - Gitlab::Checks::ChangesAccess.new( - changes, - project: project, - user_access: user_access, - protocol: 'web', - logger: logger, - push_options: push_options - ) + context 'when the spp_scan_diffs flag is enabled' do + it_behaves_like 'diff scan passed' + it_behaves_like 'diff scan detected secrets' + it_behaves_like 'diff scan detected secrets but some errors occured' + it_behaves_like 'diff scan timed out' + it_behaves_like 'diff scan failed to initialize' + it_behaves_like 'diff scan failed with invalid input' + it_behaves_like 'diff scan handles malformed blobs' + it_behaves_like 'diff scan skipped due to invalid status' + it_behaves_like 'diff scan skipped when a commit has special bypass flag' + it_behaves_like 'diff scan skipped when secret_push_protection.skip_all push option is passed' + + context 'when the protocol is web' do + subject(:secrets_check) { described_class.new(changes_access_web) } + + it_behaves_like 'scan passed' + it_behaves_like 'scan detected secrets' + it_behaves_like 'scan detected secrets but some errors occured' + it_behaves_like 'scan timed out' + it_behaves_like 'scan failed to initialize' + it_behaves_like 'scan failed with invalid input' + it_behaves_like 'scan skipped due to invalid status' + it_behaves_like 'scan skipped when a commit has special bypass flag' + it_behaves_like 'scan skipped when secret_push_protection.skip_all push option is passed' end - - subject(:secrets_check) { described_class.new(changes_access_web) } - - it_behaves_like 'scan passed' - it_behaves_like 'scan detected secrets' - it_behaves_like 'scan detected secrets but some errors occured' - it_behaves_like 'scan timed out' - it_behaves_like 'scan failed to initialize' - it_behaves_like 'scan failed with invalid input' - it_behaves_like 'scan skipped due to invalid status' - it_behaves_like 'scan skipped when a commit has special bypass flag' - it_behaves_like 'scan skipped when secret_push_protection.skip_all push option is passed' end context 'when the scan diff feature flag is not enabled' do @@ -106,6 +97,20 @@ it_behaves_like 'scan skipped due to invalid status' it_behaves_like 'scan skipped when a commit has special bypass flag' it_behaves_like 'scan skipped when secret_push_protection.skip_all push option is passed' + + context 'when the protocol is web' do + subject(:secrets_check) { described_class.new(changes_access_web) } + + it_behaves_like 'scan passed' + it_behaves_like 'scan detected secrets' + it_behaves_like 'scan detected secrets but some errors occured' + it_behaves_like 'scan timed out' + it_behaves_like 'scan failed to initialize' + it_behaves_like 'scan failed with invalid input' + it_behaves_like 'scan skipped due to invalid status' + it_behaves_like 'scan skipped when a commit has special bypass flag' + it_behaves_like 'scan skipped when secret_push_protection.skip_all push option is passed' + end end end end diff --git a/ee/spec/support/shared_contexts/secrets_check_shared_contexts.rb b/ee/spec/support/shared_contexts/secrets_check_shared_contexts.rb index ed9ba59030851e..e6ed8c88120f24 100644 --- a/ee/spec/support/shared_contexts/secrets_check_shared_contexts.rb +++ b/ee/spec/support/shared_contexts/secrets_check_shared_contexts.rb @@ -88,6 +88,17 @@ ) end + let(:changes_access_web) do + Gitlab::Checks::ChangesAccess.new( + changes, + project: project, + user_access: user_access, + protocol: 'web', + logger: logger, + push_options: push_options + ) + end + let(:delete_changes_access) do Gitlab::Checks::ChangesAccess.new( delete_changes, -- GitLab