| @@ -0,0 +1,101 @@ |
| 1 | # Ruleset: GitLab |
| 2 | # |
| 3 | # Evaluated against an audit-tools GitLab evidence package |
| 4 | # (gitlab_audit_<group>_<date>/). Note two GitLab-specific facts that shape |
| 5 | # these rules: |
| 6 | # |
| 7 | # * branch_protections lists one row *per protected branch* — there is no |
| 8 | # "protected" boolean as on GitHub. A row's existence means the branch is |
| 9 | # protected; the checks below test how strong that protection is. |
| 10 | # * audit-tools omits a CSV entirely when a collector returns no rows, so an |
| 11 | # absent table reports as "not applicable", not "pass". A rule can only |
| 12 | # speak to data that was actually collected. |
| 13 | platform: gitlab |
| 14 | |
| 15 | rules: |
| 16 | - id: gitlab.branch.no-force-push |
| 17 | title: Protected branches disallow force push |
| 18 | table: branch_protections |
| 19 | severity: high |
| 20 | controls: [SOC2:CC8.1, ISO:A.8.32, NIST:CM-6] |
| 21 | rationale: > |
| 22 | Allowing force push to a protected branch lets history be rewritten with |
| 23 | no trace, defeating the change-management record the protection exists to |
| 24 | provide. |
| 25 | remediation: Disable "Allow force push" on protected branches. |
| 26 | check: |
| 27 | type: fail_rows_where |
| 28 | when: {column: allow_force_push, op: is_true} |
| 29 | |
| 30 | - id: gitlab.branch.code-owner-approval |
| 31 | title: Protected branches require code owner approval |
| 32 | table: branch_protections |
| 33 | severity: low |
| 34 | controls: [SOC2:CC8.1, ISO:A.8.32] |
| 35 | rationale: > |
| 36 | Code owner approval routes changes to the people accountable for the |
| 37 | affected files. It is a stricter posture than a plain review requirement |
| 38 | and is not needed everywhere — hence low severity. |
| 39 | remediation: Enable "Require approval from code owners" on protected branches where ownership matters. |
| 40 | check: |
| 41 | type: fail_rows_where |
| 42 | when: {column: code_owner_approval_required, op: is_false} |
| 43 | |
| 44 | - id: gitlab.approvals.require-one |
| 45 | title: Approval rules require at least one approval |
| 46 | table: approval_rules |
| 47 | severity: medium |
| 48 | controls: [SOC2:CC8.1, ISO:A.8.32, NIST:CM-6] |
| 49 | rationale: > |
| 50 | An approval rule that requires zero approvals contributes nothing to |
| 51 | segregation of duties — a change can merge with no second person signing |
| 52 | off. |
| 53 | remediation: Set the required number of approvals to at least one on merge-blocking rules. |
| 54 | check: |
| 55 | type: fail_rows_where |
| 56 | when: {column: approvals_required, op: lt, value: 1} |
| 57 | |
| 58 | - id: gitlab.projects.no-public |
| 59 | title: Projects are not publicly visible |
| 60 | table: projects |
| 61 | severity: medium |
| 62 | controls: [SOC2:CC6.3, ISO:A.5.15, NIST:AC-6] |
| 63 | rationale: > |
| 64 | A public project exposes its source and history to anyone on the |
| 65 | internet. That is sometimes intended (open source) but should be a |
| 66 | deliberate, reviewed decision rather than a default. |
| 67 | remediation: Set project visibility to private or internal unless public exposure is intended and approved. |
| 68 | check: |
| 69 | type: fail_rows_where |
| 70 | when: {column: visibility, op: equals, value: public} |
| 71 | |
| 72 | - id: gitlab.password-policy |
| 73 | title: Instance password policy meets baseline strength |
| 74 | table: password_policy |
| 75 | severity: medium |
| 76 | controls: [ISO:A.5.17, NIST:IA-5] |
| 77 | rationale: > |
| 78 | A weak password policy undermines every password-based control. This table |
| 79 | is only present for self-hosted instances audited with an admin token; on |
| 80 | GitLab.com it is absent and this rule reports as not applicable. |
| 81 | remediation: Require a minimum length of 12 and mandate numbers and symbols in the instance settings. |
| 82 | check: |
| 83 | type: assert_row |
| 84 | require: |
| 85 | - {column: minimum_password_length, op: gte, value: 12} |
| 86 | - {column: password_number_required, op: is_true} |
| 87 | - {column: password_symbol_required, op: is_true} |
| 88 | |
| 89 | - id: gitlab.audit.logging-active |
| 90 | title: Audit event logging is producing records |
| 91 | table: audit_events |
| 92 | severity: medium |
| 93 | controls: [SOC2:CC7.2, ISO:A.8.15, NIST:AU-2] |
| 94 | rationale: > |
| 95 | The presence of audit events is direct evidence that GitLab is recording |
| 96 | security-relevant activity. Absence here means no events were collected — |
| 97 | reported as not applicable rather than as a pass or a failure. |
| 98 | remediation: Confirm audit events are enabled and retained for the group and its projects. |
| 99 | check: |
| 100 | type: require_any_row |
| 101 | when: {column: action, op: not_empty} |