diff --git a/.gitleaksignore b/.gitleaksignore index 32906f05b2accca50df84493d1de114f10c5ebcc..d52f10ebdc40ad599e6cf25a1b01d01b919a654a 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -1,2 +1,3 @@ afedb913baf4203aa688421873fdb9f94649578e:doc/api/users.md:generic-api-key:2201 spec/frontend/lib/utils/secret_detection_spec.js:generic-api-key:34 +spec/frontend/lib/utils/secret_detection_spec.js:generic-api-key:35 diff --git a/app/assets/javascripts/lib/utils/secret_detection.js b/app/assets/javascripts/lib/utils/secret_detection.js index 4d8612aeeff0a77f68ddaa01e728e93136823b18..92edd286c768566705180f87b48574e3f23cd0f2 100644 --- a/app/assets/javascripts/lib/utils/secret_detection.js +++ b/app/assets/javascripts/lib/utils/secret_detection.js @@ -32,6 +32,10 @@ export const containsSensitiveToken = (message) => { name: 'GitLab Deploy Token', regex: `gldt-[0-9a-zA-Z_-]{20}`, }, + { + name: 'GitLab SCIM OAuth Access Token', + regex: `glsoat-[0-9a-zA-Z_-]{20}`, + }, ]; for (const rule of sensitiveDataPatterns) { diff --git a/config/feature_flags/development/prefix_scim_tokens.yml b/config/feature_flags/development/prefix_scim_tokens.yml new file mode 100644 index 0000000000000000000000000000000000000000..297327f26d2ce728a13ca7cbfc45bf10f1af2496 --- /dev/null +++ b/config/feature_flags/development/prefix_scim_tokens.yml @@ -0,0 +1,8 @@ +--- +name: prefix_scim_tokens +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139737 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/435423 +milestone: '16.8' +type: development +group: group::authentication +default_enabled: false diff --git a/config/gitleaks.toml b/config/gitleaks.toml index a492b38fdf96541da486f1452d6f1bdaacbb06bb..0983a34ca7105964dce7038dba2a01e6e66cb919 100644 --- a/config/gitleaks.toml +++ b/config/gitleaks.toml @@ -13,6 +13,7 @@ path = "/gitleaks.toml" # spec/frontend/lib/utils/secret_detection_spec.js "glpat-cgyKc1k_AsnEpmP-5fRL", "gldt-cgyKc1k_AsnEpmP-5fRL", + "glsoat-cgyKc1k_AsnEpmP-5fRL", # spec/frontend/lib/utils/secret_detection_spec.js "GlPat-abcdefghijklmnopqrstuvwxyz", # doc/development/sec/token_revocation_api.md diff --git a/doc/security/token_overview.md b/doc/security/token_overview.md index 4555459e7c5ff28574c758223fd7b1832ed6fa41..4498ee893a784f15e2a0311886755bc69bff9281 100644 --- a/doc/security/token_overview.md +++ b/doc/security/token_overview.md @@ -245,6 +245,7 @@ The following tables show the prefixes for each type of token where applicable. | Incoming mail token | `glimt-` | | GitLab Agent for Kubernetes token | `glagent-` | | GitLab session cookies | `_gitlab_session=` | +| SCIM Tokens | `glsoat-` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435096) in GitLab 16.8 behind a feature flag named `prefix_scim_tokens`. Disabled by default.) | ### External system tokens diff --git a/ee/app/models/scim_oauth_access_token.rb b/ee/app/models/scim_oauth_access_token.rb index 4bea5a91b0fa04d22fb7cae1402ee7e89fe28641..9ecd6aa105d6f3422ef4e3a35abc5082aee2909f 100644 --- a/ee/app/models/scim_oauth_access_token.rb +++ b/ee/app/models/scim_oauth_access_token.rb @@ -3,9 +3,11 @@ class ScimOauthAccessToken < ApplicationRecord include TokenAuthenticatable + TOKEN_PREFIX = 'glsoat-' + belongs_to :group, optional: true - add_authentication_token_field :token, encrypted: :required + add_authentication_token_field :token, encrypted: :required, format_with_prefix: :prefix_for_token before_save :ensure_token @@ -31,4 +33,8 @@ def self.find_for_instance def as_entity_json ScimOauthAccessTokenEntity.new(self).as_json end + + def prefix_for_token + Feature.enabled?(:prefix_scim_tokens) ? TOKEN_PREFIX : '' + end end diff --git a/ee/spec/models/scim_oauth_access_token_spec.rb b/ee/spec/models/scim_oauth_access_token_spec.rb index 561f77d32aa2d8032d098157aed13765fc5fdfe4..4a7274dcf5346fbee20ccc8f0d14fcdc83685214 100644 --- a/ee/spec/models/scim_oauth_access_token_spec.rb +++ b/ee/spec/models/scim_oauth_access_token_spec.rb @@ -93,5 +93,23 @@ expect(scim_token.token).to be_a(String) end + + it 'is prefixed' do + scim_token = described_class.create! + + expect(scim_token.token).to match(/^glsoat-[\w-]{20}$/) + end + + context 'when feature flag is disabled' do + before do + stub_feature_flags(prefix_scim_tokens: false) + end + + it 'is not prefixed' do + scim_token = described_class.create! + + expect(scim_token.token).to match(/^[\w-]{20}$/) + end + end end end diff --git a/spec/frontend/lib/utils/secret_detection_spec.js b/spec/frontend/lib/utils/secret_detection_spec.js index a8da6e8969fa986b1ec8029f240f0a65e8b2af5d..0d1bf1abbaab6a4ed7f0e96f3375177dda1c9aa8 100644 --- a/spec/frontend/lib/utils/secret_detection_spec.js +++ b/spec/frontend/lib/utils/secret_detection_spec.js @@ -32,6 +32,7 @@ describe('containsSensitiveToken', () => { 'https://example.com/feed?feed_token=123456789_abcdefghij', 'glpat-1234567890 and feed_token=ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'token: gldt-cgyKc1k_AsnEpmP-5fRL', + 'curl "https://gitlab.example.com/api/v4/groups/33/scim/identities" --header "PRIVATE-TOKEN: glsoat-cgyKc1k_AsnEpmP-5fRL', ]; it.each(sensitiveMessages)('returns true for message: %s', (message) => {