kingfisher/crates/kingfisher-rules/data/rules/gitlab.yml

495 lines
12 KiB
YAML

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-
(?<base64_payload>[0-9A-Za-z_-]{27,300})
\.
(?<version>01)
\.
(?<base36_payload_length>[0-9a-zA-Z]{2})
(?<crc32>[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