rules: - name: GitLab Private Token id: kingfisher.gitlab.1 pattern: | (?x) \b ( glpat- [0-9A-Za-z_-]{20} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.5 confidence: medium examples: - glpat-kSaPeOD_-T0JxMi3p28B - | docker build -t tweedledee \ -f Dockerfile \ --build-arg 'GO_REPO_TOKEN=glpat-tFrjFXD7soVU2fqxuDMh' \ references: - https://github.com/diffblue/gitlab/blob/39c63ee83369bf5353256a6b95f3116728edd102/doc/api/personal_access_tokens.md - https://docs.gitlab.com/api/personal_access_tokens/ validation: type: Http content: request: headers: PRIVATE-TOKEN: '{{ TOKEN }}' method: GET response_matcher: - report_response: true - type: WordMatch words: - '"id"' url: '{{ GITLAB_API_BASE_URL }}/personal_access_tokens/self' revocation: type: Http content: request: headers: PRIVATE-TOKEN: '{{ TOKEN }}' method: DELETE response_matcher: - report_response: true - type: StatusMatch status: [204] url: '{{ GITLAB_API_BASE_URL }}/personal_access_tokens/self' - name: GitLab Runner Registration Token id: kingfisher.gitlab.2 pattern: | (?x) \b ( GR1348941[0-9A-Za-z_-]{20} ) \b pattern_requirements: min_digits: 2 examples: - | sudo gitlab-runner register \ --non-interactive \ --url "https://gitlab.com/" \ --registration-token "GR1348941_iAgdMy7a3NhZaa5oNoH" \ --executor "docker" \ --docker-image ubuntu:latest \ --description "docker-runner" \ --tag-list "docker, CICD, App" \ --run-untagged="true" \ --locked="false" \ --access-level="not_protected" references: - https://docs.gitlab.com/api/runners/ validation: type: Http content: request: method: POST headers: Content-Type: application/x-www-form-urlencoded Accept: application/json body: token={{ TOKEN }} response_matcher: - report_response: true - type: StatusMatch status: 200 - type: WordMatch words: - '"token is missing"' - '"403 Forbidden"' negative: true url: '{{ GITLAB_API_BASE_URL }}/runners/verify' - name: GitLab Pipeline Trigger Token id: kingfisher.gitlab.3 pattern: | (?x) \b ( glptt-[0-9a-fA-F]{40} ) pattern_requirements: min_digits: 2 examples: - | curl \ -X POST \ --fail \ --no-progress-meter \ -F token=glptt-0d66598d696a02da33fb65e2a041f607c68ea50d \ -F ref=main references: - https://docs.gitlab.com/api/pipeline_triggers/ validation: type: Http content: request: headers: PRIVATE-TOKEN: '{{ TOKEN }}' method: GET response_matcher: - report_response: true - type: StatusMatch status: - 200 - type: WordMatch words: - '"token is missing"' - '"403 Forbidden"' negative: true url: '{{ GITLAB_API_BASE_URL }}/ci/pipeline_triggers/{{ TOKEN }}' - name: GitLab Private Token - Routable Format id: kingfisher.gitlab.4 pattern: | (?x) \b ( glpat- (?[0-9A-Za-z_-]{27,300}) \. (?01) \. (?[0-9a-zA-Z]{2}) (?[0-9a-z]{7}) ) \b pattern_requirements: min_digits: 2 # GitLab's RoutableTokenGenerator renders the CRC32 digest as lowercase # base36 with a fixed width of 7 characters. The regex and checksum # expectation mirror that encoding so we only report matches that carry a # valid GitLab-style checksum. checksum: actual: template: "{{ crc32 }}" requires_capture: crc32 expected: "{{ \"glpat-\" | append: base64_payload | append: \".01.\" | append: base36_payload_length | crc32 | base36: 7 }}" skip_if_missing: true min_entropy: 3.5 confidence: medium examples: - glpat-vSY1cyL948aAB440qB6L4zlu9OzsUmEV.01.0w0sfevch references: - https://github.com/diffblue/gitlab/blob/39c63ee83369bf5353256a6b95f3116728edd102/doc/api/personal_access_tokens.md - https://docs.gitlab.com/api/personal_access_tokens/ validation: type: Http content: request: headers: PRIVATE-TOKEN: '{{ TOKEN }}' method: GET response_matcher: - report_response: true - type: WordMatch words: - '"id"' url: '{{ GITLAB_API_BASE_URL }}/personal_access_tokens/self' revocation: type: Http content: request: headers: PRIVATE-TOKEN: '{{ TOKEN }}' method: DELETE response_matcher: - report_response: true - type: StatusMatch status: [204] url: '{{ GITLAB_API_BASE_URL }}/personal_access_tokens/self' - name: GitLab CI/CD Job Token id: kingfisher.gitlab.5 pattern: | (?x) \b ( glcbt- [0-9a-zA-Z]{1,5} _ [0-9a-zA-Z_-]{20} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - glcbt-ab12_xY9kLmNpQrStUvWxYz01 - 'CI_JOB_TOKEN=glcbt-a1b2c_3dEfGhIjKlMnOpQrStUv' references: - https://docs.gitlab.com/ci/jobs/ci_job_token/ - https://docs.gitlab.com/api/jobs/ validation: type: Http content: request: method: GET url: '{{ GITLAB_API_BASE_URL }}/job' headers: JOB-TOKEN: '{{ TOKEN }}' response_matcher: - report_response: true - type: StatusMatch status: [200] - type: JsonValid - type: WordMatch match_all_words: true words: - '"id"' - '"status"' # Revocation not added: CI/CD job tokens are short-lived and automatically # invalidated when the job finishes. - name: GitLab Deploy Token id: kingfisher.gitlab.6 pattern: | (?x) \b ( gldt- [0-9a-zA-Z_-]{20} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - gldt-xY9kLmNpQrStUvWxYz01 - 'DEPLOY_TOKEN=gldt-3dEfGhIjK4MnOpQrStUv' references: - https://docs.gitlab.com/user/project/deploy_tokens/ # Validation not added: deploy tokens authenticate via HTTP basic auth # (username + token as password) and require the deploy token username, # which varies per token and is not captured by this rule. - name: GitLab Feature Flag Client Token id: kingfisher.gitlab.7 pattern: | (?x) \b ( glffct- [0-9a-zA-Z_-]{20} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - glffct-xY9kLmNpQrStUvWxYz01 references: - https://docs.gitlab.com/operations/feature_flags/ - name: GitLab Feed Token id: kingfisher.gitlab.8 pattern: | (?x) \b ( glft- [0-9a-zA-Z_-]{20} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - glft-xY9kLmNpQrStUvWxYz01 references: - https://docs.gitlab.com/user/profile/contributions_calendar/#feed-token - name: GitLab Incoming Mail Token id: kingfisher.gitlab.9 pattern: | (?x) \b ( glimt- [0-9a-zA-Z_-]{25} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - glimt-xY9kLmNpQrStUvWxYz0123456 references: - https://docs.gitlab.com/administration/incoming_email/ - name: GitLab Kubernetes Agent Token id: kingfisher.gitlab.10 pattern: | (?x) \b ( glagent- [0-9a-zA-Z_-]{50} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - glagent-xY9kLmNpQrStUvWxYz01234567890abcdefghijklmnopqrstu references: - https://docs.gitlab.com/user/clusters/agent/ - name: GitLab OAuth Application Secret id: kingfisher.gitlab.11 pattern: | (?x) \b ( gloas- [0-9a-zA-Z_-]{64} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - gloas-xY9kLmNpQrStUvWxYz01234567890abcdefghijklmnopqrstuvwxyz012345678 references: - https://docs.gitlab.com/integration/oauth_provider/ - name: GitLab Runner Authentication Token id: kingfisher.gitlab.12 pattern: | (?x) \b ( glrt- [0-9a-zA-Z_-]{20} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - glrt-xY9kLmNpQrStUvWxYz01 - | gitlab-runner register \ --url https://gitlab.com \ --token glrt-3dEfGhIjK4MnOpQrStUv references: - https://docs.gitlab.com/runner/register/ validation: type: Http content: request: method: POST headers: Content-Type: application/x-www-form-urlencoded Accept: application/json body: token={{ TOKEN }} response_matcher: - report_response: true - type: StatusMatch status: 200 - type: WordMatch words: - '"token is missing"' - '"403 Forbidden"' negative: true url: '{{ GITLAB_API_BASE_URL }}/runners/verify' - name: GitLab Runner Authentication Token - Routable Format id: kingfisher.gitlab.13 pattern: | (?x) \b ( glrt-t \d _ [0-9a-zA-Z_-]{27,300} \. [0-9a-z]{2} [0-9a-z]{7} ) \b pattern_requirements: min_digits: 2 min_entropy: 4.0 confidence: medium examples: - glrt-t1_xY9kLmNpQrStUvWxYz01234567890.01abc1234 references: - https://docs.gitlab.com/runner/register/ validation: type: Http content: request: method: POST headers: Content-Type: application/x-www-form-urlencoded Accept: application/json body: token={{ TOKEN }} response_matcher: - report_response: true - type: StatusMatch status: 200 - type: WordMatch words: - '"token is missing"' - '"403 Forbidden"' negative: true url: '{{ GITLAB_API_BASE_URL }}/runners/verify' - name: GitLab SCIM Token id: kingfisher.gitlab.14 pattern: | (?x) \b ( glsoat- [0-9a-zA-Z_-]{20} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - glsoat-xY9kLmNpQrStUvWxYz01 references: - https://docs.gitlab.com/api/scim/ - name: GitLab Session Cookie id: kingfisher.gitlab.15 pattern: | (?x) (?:^|[;\s]) _gitlab_session= ( [0-9a-f]{32} ) \b pattern_requirements: min_digits: 2 min_entropy: 3.0 confidence: medium examples: - '_gitlab_session=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6' - 'Cookie: _gitlab_session=0f1e2d3c4b5a69788796a5b4c3d2e1f0' references: - https://docs.gitlab.com/ validation: type: Http content: request: method: GET url: '{{ GITLAB_API_BASE_URL }}/user' headers: Cookie: "_gitlab_session={{ TOKEN }}" response_matcher: - report_response: true - type: StatusMatch status: [200] - type: WordMatch words: - '"id"' - '"username"' match_all_words: true