README
ΒΆ
- Find compliance issues in your GitLab repositories and their CI/CD pipelines
- Download and store compliance results as JSON artifacts for auditability and traceability
- Customize controls
πΈ Preview
β Compliance Passed

Contents
- Plumber
- Preview
- Quick Start (GitLab CI)
- Compliance Controls
- Customize
- Test Locally (CLI)
- Example Output
- Configuration
- CLI Reference
- Troubleshooting
- Contributing
- License
π Quick Start (GitLab CI)
1. Create a GitLab token with read_api + read_repository scopes and add it as GITLAB_TOKEN in Settings β CI/CD β Variables (masked & protected recommended).
2. Add to your .gitlab-ci.yml:
include:
- component: gitlab.com/getplumber/plumber/plumber@~latest
β That's it! Plumber will analyze your CI/CD pipeline for compliance issues.
π‘ Everything is customizable β GitLab URL, branch, threshold, and more. See Customize below.
β οΈ Self-Hosted GitLab
If you're running a self-hosted GitLab instance, you'll need to create your own component since gitlab.com components can't be accessed from your instance.
Option 1: Fork our GitLab component to your instance
Option 2: Create a component using templates/plumber.yml as a base
See GitLab's CI/CD component documentation for setup instructions.
π― Compliance Controls
Plumber scans your GitLab CI/CD configuration and run following controls:
- π·οΈ Authorized image tags β Flags
latest,dev, and other non-reproducible tags for container images used in CI/CD pipelines - π Authorized image sources β Ensures container images used in your CI/CD pipelines come from approved sources
- π‘οΈ Branch protection β Verifies that repository branches are properly protected
- Other controls will come
βοΈ Customize
Override any input to fit your needs:
include:
- component: gitlab.com/getplumber/plumber/plumber@~latest
inputs:
# Target (defaults to current project)
server_url: https://gitlab.example.com # Self-hosted GitLab (default: $CI_SERVER_URL)
project_path: other-group/other-project # Analyze a different project (default: $CI_PROJECT_PATH)
branch: develop # Analyze a specific branch (default: $CI_COMMIT_REF_NAME)
# Compliance
threshold: 80 # Minimum % to pass (default: 100)
config_file: configs/my-plumber.yaml # Custom config path (relative to repo root)
# Output
output_file: plumber-report.json # Export JSON report (default: plumber-report.json )
print_output: true # Print to stdout (default: true)
# Job behavior
stage: test # Run in a different stage (default: .pre)
allow_failure: true # Don't block pipeline on failure (default: false)
gitlab_token: $MY_CUSTOM_TOKEN # Use a different variable name (default: $GITLAB_TOKEN)
verbose: true # Enable debug output for troubleshooting (default: false)
All Inputs
| Input | Default | Description |
|---|---|---|
server_url |
$CI_SERVER_URL |
GitLab instance URL |
project_path |
$CI_PROJECT_PATH |
Project to analyze |
branch |
$CI_COMMIT_REF_NAME |
Branch to analyze |
gitlab_token |
$GITLAB_TOKEN |
GitLab API token (requires read_api + read_repository scopes) |
threshold |
100 |
Minimum compliance % to pass |
config_file |
(auto-detect) | Path to config file (relative to repo root). Auto-detects .plumber.yaml in repo, falls back to default |
output_file |
plumber-report.json |
Path to write JSON results |
print_output |
true |
Print text output to stdout |
stage |
.pre |
Pipeline stage for the job |
image |
getplumber/plumber:0.1 |
Docker image to use |
allow_failure |
false |
Allow job to fail without blocking |
verbose |
false |
Enable debug output for troubleshooting |
π» Test Locally (CLI)
Download Binary
Pre-built binaries are available for each release:
# Linux (amd64)
curl -LO https://github.com/getplumber/plumber/releases/latest/download/plumber-linux-amd64
chmod +x plumber-linux-amd64
sudo mv plumber-linux-amd64 /usr/local/bin/plumber
# Linux (arm64)
curl -LO https://github.com/getplumber/plumber/releases/latest/download/plumber-linux-arm64
chmod +x plumber-linux-arm64
sudo mv plumber-linux-arm64 /usr/local/bin/plumber
# macOS (Apple Silicon)
curl -LO https://github.com/getplumber/plumber/releases/latest/download/plumber-darwin-arm64
chmod +x plumber-darwin-arm64
sudo mv plumber-darwin-arm64 /usr/local/bin/plumber
# macOS (Intel)
curl -LO https://github.com/getplumber/plumber/releases/latest/download/plumber-darwin-amd64
chmod +x plumber-darwin-amd64
sudo mv plumber-darwin-amd64 /usr/local/bin/plumber
# Windows (PowerShell)
Invoke-WebRequest -Uri https://github.com/getplumber/plumber/releases/latest/download/plumber-windows-amd64.exe -OutFile plumber.exe
Verify checksum (optional):
curl -LO https://github.com/getplumber/plumber/releases/latest/download/checksums.txt
sha256sum -c checksums.txt --ignore-missing
Run analysis:
export GITLAB_TOKEN=glpat-xxxx
plumber analyze \
--gitlab-url https://gitlab.com \
--project mygroup/myproject \
--branch main \
--config .plumber.yaml \
--threshold 100
Docker
# Run analysis
docker run --rm \
-e GITLAB_TOKEN=glpat-xxxx \
getplumber/plumber:latest analyze \
--gitlab-url https://gitlab.com \
--project mygroup/myproject \
--branch main \
--config /.plumber.yaml \
--threshold 100
# Save JSON output locally
docker run --rm \
-e GITLAB_TOKEN=glpat-xxxx \
-v $(pwd):/output \
getplumber/plumber:latest analyze \
--gitlab-url https://gitlab.com \
--project mygroup/myproject \
--branch main \
--config /.plumber.yaml \
--threshold 100 \
--output /output/results.json
Build from Source
git clone https://github.com/getplumber/plumber.git
cd plumber
go build -o plumber .
export GITLAB_TOKEN=glpat-xxxx
./plumber analyze \
--gitlab-url https://gitlab.com \
--project mygroup/myproject \
--branch main \
--config .plumber.yaml \
--threshold 100
π Example Output
Project: mygroup/myproject
ββββββββββββββββββββββββββββββββββββββββββββββββββ
Container images must not use forbidden tags (100.0% compliant)
ββββββββββββββββββββββββββββββββββββββββββββββββββ
Total Images: 10
Using Forbidden Tags: 0
ββββββββββββββββββββββββββββββββββββββββββββββββββ
Container images must come from authorized sources (0.0% compliant)
ββββββββββββββββββββββββββββββββββββββββββββββββββ
Total Images: 10
Authorized: 6
Unauthorized: 4
Unauthorized Images Found:
β’ Job 'sls_scan' uses unauthorized image: docker.io/shiftleft/sast-scan:v1.15.1
β’ Job 'gitleaks' uses unauthorized image: docker.io/zricethezav/gitleaks:v8.15.0
β’ Job 'golint' uses unauthorized image: docker.io/docker/golangci-lint:2.5.0-go1.25.3
β’ Job 'tag-production-image' uses unauthorized image: gcr.io/go-containerregistry/crane:debug
ββββββββββββββββββββββββββββββββββββββββββββββββββ
Branch must be protected (100.0% compliant)
ββββββββββββββββββββββββββββββββββββββββββββββββββ
Total Branches: 8
Branches to Protect: 1
Protected Branches: 1
Unprotected: 0
Non-Compliant: 0
ββββββββββββββββββββ
Summary
ββββββββββββββββββββ
Status: FAILED β
Issues
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ€βββββββββββ
β Control β Issues β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββΌβββββββββββ’
β Container images must not use forbidden tags β 0 β
β Container images must come from authorized sources β 4 β
β Branch must be protected β 0 β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ§βββββββββββ
Compliance
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ€βββββββββββββ€βββββββββββ
β Control β Compliance β Status β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββΌβββββββββββββΌβββββββββββ’
β Container images must not use forbidden tags β 100.0% β β β
β Container images must come from authorized sources β 0.0% β β β
β Branch must be protected β 100.0% β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββΌβββββββββββββΌβββββββββββ’
β Total (required: 100%) β 66.7% β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ§βββββββββββββ§βββββββββββ
π‘ JSON Output: When using
--output, results are saved as JSON. Seeoutput-example.jsonfor the full structure.
π Configuration
GitLab CI Component
The component automatically detects your configuration using this priority:
config_fileinput set β Uses your specified path (relative to repo root).plumber.yamlin repo root β Uses your repo's config file- No config found β Uses the default configuration embedded in the container
CLI
When using the CLI directly, you must explicitly provide the --config flag β there is no auto-detection.
To customize controls, create a .plumber.yaml file.
See the full configuration reference for all options.
π CLI Reference
plumber analyze [flags]
Flags:
--gitlab-url GitLab instance URL (required)
--project Project path, e.g., group/project (required)
--config Path to .plumber.yaml (required)
--threshold Minimum compliance % to pass (required)
--branch Branch to analyze (default: project default)
--output Write JSON results to file
--print Print text output (default: true)
Environment:
GITLAB_TOKEN GitLab API token (required)
Exit Codes:
0 Passed (compliance β₯ threshold)
1 Failed (compliance < threshold or error)
π§ Troubleshooting
| Issue | Solution |
|---|---|
GITLAB_TOKEN environment variable is required |
Add GITLAB_TOKEN in CI/CD Variables |
401 Unauthorized |
Token should have read_api + read_repository scopes |
403 Forbidden on MR settings |
Expected on non-Premium GitLab; continues without that data |
π€ Contributing
Contributions are welcome! Please read our Contributing Guide for details on:
- How to report issues
- How to submit pull requests
- Coding and commit conventions
- The review process
π License
Documentation
ΒΆ
There is no documentation for this package.