gitlab

v0.1.0 collector

Collects GitLab group security posture metrics

Install

epack install collector gitlab

Adds to epack.yaml, resolves dependencies, downloads binary.

Usage

Run all configured collectors and build a pack:

epack collect

Runs all collectors in epack.yaml and outputs an evidence pack.

Configuration

Or add manually to epack.yaml:

collectors:
  gitlab:
    source: https://github.com/locktivity/epack-collector-gitlab

Then run epack install to lock and sync.

GitLab Collector

The collector reads the GitLab REST API v4 for a configured group and emits security posture evidence. It includes projects in subgroups and excludes projects shared into the group.

What it collects

  • Default-branch protection and matching wildcard rules
  • Project merge request approval settings and branch-scoped approval rules
  • Secret push protection and the pipeline-required setting
  • Group 2FA enforcement and, at audit+, project-creation policy and sharing lock
  • Group member and project inventories at audit+
  • Webhook counts, deploy-key counts, and available-runner inventory at audit+
  • Webhook hosts, deploy-key details, and seven-day group audit events at internal

It does not inspect repository contents, CI configuration, or CODEOWNERS files. It does not collect SAST/dependency-scanning adoption or vulnerability findings. See collection levels for the emitted fields and limits.

Hosting modes

  • GitLab.com: default instance URL
  • Self-managed: configure base_url
  • GitLab Dedicated: configure the dedicated instance URL

The available fields depend on GitLab version, license, and token permissions.

Output

Successful runs emit two artifacts at every collection level:

  1. artifacts/gitlab.json: detailed GitLab-specific posture
  2. artifacts/gitlab.vcs-posture.json: normalized evidencepack/vcs-posture@v1 posture

The normalized output maps group 2FA, project selection coverage, MR/approval percentages, and pipeline-required percentages from the detailed artifact. secret_scanning_pct currently uses secret push protection adoption as a proxy; it does not measure pipeline secret detection.

Output limitations

Percentages describe the projects visible to the token after filtering. projects_coverage is the percentage of API-listed projects selected by the filters, not a measurement of all projects the organization owns. Archived and empty projects remain in the denominator. security_features_coverage is the arithmetic mean of secret push protection and pipeline-required coverage, rounded down to an integer.

Pipeline coverage reports the project's only_allow_merge_if_pipeline_succeeds flag. It does not inspect pipeline contents or prove that every change ran checks. Code owner coverage reports the branch flag; it does not verify that a CODEOWNERS file exists or covers all paths. Approval inventory records the maximum applicable approval count, not a complete copy of approval rules or approver identities.

The normalized signed_commits_pct, vuln_alerts_pct, and code_scanning_pct are fixed at zero because this collector does not measure them. Each is listed in unavailable_sources with an explanation. unavailable_sources also includes runtime diagnostics from permission errors and endpoint failures. Projects that omit secret_push_protection_enabled (due to tier or role restrictions) emit a diagnostic noting how many projects could not report the field.

Endpoint failures appear in diagnostics where collection can continue. A failed optional endpoint can lower coverage or counts, and counts of zero can reflect inaccessible data. Inspect diagnostics alongside the metrics. HTTP 401 fails collection at every surface; non-permission errors retrieving the group or project list also fail collection.

Group members, group hooks, runners, and group audit events retain their group scope when projects are filtered. For complete group audit events, use Owner: lower roles can return an apparently successful list containing only the token owner's actions.

Configuration

Authentication

Set GITLAB_TOKEN to a group or personal access token with read_api scope. A group access token creates its own bot identity; a personal token can belong to a dedicated service account. Assign a role appropriate to the surfaces you need.

For a group access token, navigate to your GitLab group > Settings > Access tokens, create the token, and provide it through the GITLAB_TOKEN environment variable and the secrets entry below. Personal tokens can be created under your GitLab profile's access-token settings.

The collector does not call the Users API, so it does not require read_user. Adding that scope does not make hidden member 2FA fields available.

epack.yaml

stream: myorg/gitlab-posture

collectors:
  gitlab:
    source: locktivity/epack-collector-gitlab@^0.1
    config:
      group: my-organization
      level: trust
      # base_url: https://gitlab.example.com
      # include_patterns: ["backend-*"]
      # exclude_patterns: ["archived-*"]
    secrets:
      - GITLAB_TOKEN

Configuration options

Key Required Default Description
group Yes Group path, including a subgroup path, or numeric ID supplied as a string
base_url No https://gitlab.com Instance URL; the collector appends /api/v4
level No trust trust, audit, or internal; unknown values fall back to trust with an SDK warning
include_patterns No ["*"] Case-sensitive globs matching project display names
exclude_patterns No [] Project display-name globs evaluated before includes

Filters match name, not path_with_namespace. For example, backend-* matches a project named backend-api, regardless of its namespace. Projects in subgroups are included; projects shared into the group are excluded. Archived projects are included unless filtered out. Percentages use all included projects as their denominator.

Project filters apply to project metrics, project inventory, project webhooks, and deploy keys. Group members, group webhooks, runners, and group audit events keep their group scope. The configured group and filter patterns appear in trust output too.

Supply pattern lists as arrays of strings with valid glob syntax. Invalid globs and non-string list entries are rejected before collection begins.

Secrets

Secret Required Description
GITLAB_TOKEN Yes GitLab access token; never written into the artifacts

Self-managed and Dedicated instances

Set base_url to the instance URL, without an /api/v4 suffix:

config:
  group: my-org
  base_url: https://gitlab.example.com

For GitLab Dedicated, use the URL of your dedicated instance in the same way.

Roles, scopes, and tiers

Surface Collection level Requirements and limitations
Group settings, projects, branch protection trust+ read_api; visibility depends on token membership and role
Approval settings and rules trust+ Premium+; permissions can vary between the two endpoints
Secret push protection status trust+ Ultimate; status is exposed to Developer, Security Manager, Maintainer, or Owner where supported
Members audit+ read_api; inherited and invited membership follows the API's visibility rules
Member 2FA status audit+ API field introduced in GitLab 19.4 and visible to group Owners and administrators; missing values remain null
Project webhooks and deploy keys audit+ Maintainer or above
Group webhooks audit+ Premium+, Owner or administrator
Runners available to the group audit+ Current API documentation requires Owner/Auditor or custom admin_runners, and manage_runner scope
Group audit events internal Premium+; Owner for all users' events; Developer/Maintainer can receive only their own events

Requirements vary with GitLab version. Consult the Projects API, Groups members API, Runners API, and Audit events API.

Optional endpoint failures emit diagnostics. HTTP 401 is always fatal; non-permission failures fetching the group or project list are fatal too. A successful response can omit restricted fields without a diagnostic. Group webhook and audit-event HTTP 403 diagnostics currently mention Premium even when the cause is insufficient role. Runner permission diagnostics currently mention Maintainer, although the group-list endpoint has stricter documented requirements.

Examples

Basic usage (GitLab.com)

# epack.yaml
stream: myorg/gitlab-posture

collectors:
  gitlab:
    source: locktivity/epack-collector-gitlab@^0.1
    config:
      group: my-organization
    secrets:
      - GITLAB_TOKEN
export GITLAB_TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx"
epack collect

Self-managed instance

collectors:
  gitlab:
    source: locktivity/epack-collector-gitlab@^0.1
    config:
      group: engineering
      base_url: https://gitlab.internal.company.com
    secrets:
      - GITLAB_TOKEN

Filtered project collection

collectors:
  gitlab:
    source: locktivity/epack-collector-gitlab@^0.1
    config:
      group: my-organization
      include_patterns:
        - "backend-*"
        - "frontend-*"
      exclude_patterns:
        - "*-archived"
    secrets:
      - GITLAB_TOKEN

Audit-level collection

Set the collection level in the collector configuration:

stream: myorg/gitlab-posture

collectors:
  gitlab:
    source: locktivity/epack-collector-gitlab@^0.1
    config:
      group: my-organization
      level: audit
    secrets:
      - GITLAB_TOKEN
epack collect

Sample trust-level output

{
  "schema_version": "1.0.0",
  "collected_at": "2026-09-18T12:00:00Z",
  "collected_at_level": "trust",
  "group": "my-organization",
  "scope": {
    "include_patterns": ["*"],
    "exclude_patterns": [],
    "projects_coverage": 100
  },
  "posture": {
    "branch_protection_coverage": 95,
    "security_features_coverage": 72
  },
  "access_control": {
    "two_factor_required": true
  },
  "branch_protection_rules": {
    "merge_request_required": 92,
    "approving_reviews": 78,
    "code_owner_approval": 45,
    "no_force_push": 95
  },
  "security_features": {
    "secret_push_protection": 60,
    "pipeline_required": 84
  }
}

This is an illustrative output. diagnostics is omitted when there are no warnings or permission errors. The 72% security-features coverage above is the mean of 60% secret push protection and 84% pipeline-required coverage. See output limitations before interpreting zeros as disabled controls.

v0.1.0 Latest
2026-10-08

**Full Changelog**: https://github.com/locktivity/epack-collector-gitlab/commits/v0.1.0

darwin/amd64 darwin/arm64 linux/amd64 linux/arm64

Details

Publisher
locktivity
Latest
v0.1.0
Protocol
v1

Platforms

darwin/amd64 darwin/arm64 linux/amd64 linux/arm64

Links