audit-labs/audit-report

Turn audit-tools evidence packages into control-mapped, auditor-ready reports.

clone: git clone https://gitbay.org/audit-labs/audit-report.git

v1.0.0: audit_report/rulesets/gitlab.yaml · raw

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