Plumber
Open source CLI to check compliance of your GitLab CI/CD pipelines and repos
Install / Use
/learn @getplumber/PlumberREADME
🤔 What is Plumber?
Plumber is a compliance scanner for GitLab. It reads your .gitlab-ci.yml and repository settings, then checks for security and compliance issues like:
- Container images using mutable tags (
latest,dev) - Container images from untrusted registries
- Unprotected branches
- Hardcoded jobs not from external includes/components
- Outdated includes/templates
- Forbidden version patterns (e.g.,
main,HEAD) - Missing required components or templates
- Debug trace variables (
CI_DEBUG_TRACE) leaking secrets in job logs - Unsafe variable injection via
eval/sh -c/bash -c(OWASP CICD-SEC-1) - Weakened security jobs (
allow_failure: true,when: manual,rules: [{when: never}]) on SAST, Secret Detection, and other scanners (OWASP CICD-SEC-4)
How does it work? Plumber connects to your GitLab instance via API, analyzes your pipeline configuration, and reports any issues it finds. You define what's allowed in a config file (.plumber.yaml), and Plumber tells you if your project complies. When running locally from your git repo, Plumber uses your local CI configuration file (.gitlab-ci.yml by default, or a custom path) allowing you to validate changes before pushing.
🚀 Two Ways to Use Plumber
Choose one of these methods. You don't need both:
| Method | Best for | How it works |
|--------|----------|--------------|
| CLI | Quick evaluation, local testing, one-off scans | Install binary and run from terminal |
| GitLab CI Component | Automated checks on every pipeline run | Add 2 lines to your .gitlab-ci.yml |
📖 Table of Contents
- What is Plumber?
- CLI
- GitLab CI Component
- Configuration
- Artifacts & Outputs
- GitLab Integration
- Installation
- CLI Reference
- Self-Hosted GitLab
- Troubleshooting
- See it in action
- Blog Posts & Articles
Option 1: CLI
Try Plumber in 2 minutes! No commits, no CI changes, just run it.
Step 1: Install
Choose one of the following:
Homebrew
brew tap getplumber/plumber
brew install plumber
Mise
mise use -g github:getplumber/plumber
Requires mise activation in your shell, or run with
mise exec -- plumber.
Direct Download
# For Linux/MacOs
curl -LO "https://github.com/getplumber/plumber/releases/latest/download/plumber-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')"
chmod +x plumber-* && sudo mv plumber-* /usr/local/bin/plumber
📦 See Installation for Windows, Docker, or building from source.
Step 2: Generate a Config File
plumber config generate
This creates .plumber.yaml with default compliance rules. You can customize it later.
Step 3: Create & Set Your Token
- In GitLab, go to User Settings → Access Tokens (direct link)
- Create a Personal Access Token with
read_api+read_repositoryscopes- Project Access Tokens also work: create one inside your project: Settings → Access Tokens with the same scopes and at least Maintainer role
- Export it in your terminal:
⚠️ Important: The token must belong to a user (or project bot) with Maintainer role (or higher) on the project to access branch protection settings and other project configurations.
export GITLAB_TOKEN=glpat-xxxx
Step 4: Run Analysis
Plumber auto-detects the GitLab URL and project from your git remote but requires the remote to be set to 'origin'.
# if in git remote with remote = origin, run:
plumber analyze
# Or specify the project explicitly:
plumber analyze --gitlab-url https://gitlab.com --project mygroup/myproject
It reads your .plumber.yaml config and outputs a compliance report. You can also tell it to store the output in JSON format with the --output flag.
Local CI Configuration
When running from your project's git repository, Plumber automatically uses your local CI configuration file instead of fetching it from the remote. This lets you validate changes before pushing.
The CI configuration file path is resolved by priority:
--ci-config-pathis specified → uses that path (both locally and remotely)- Auto-detected from GitLab project settings → uses the project's configured CI config path (usually
.gitlab-ci.yml)
The source of the CI configuration file (local vs. remote) is resolved by priority:
--branchis specified → always uses the remote file from that branch- In a git repo and the local repo matches the analyzed project → uses the local file
- Otherwise → uses the remote file from the project's default branch
If the local CI configuration is invalid, Plumber exits with an error showing the specific validation messages from GitLab so you can fix issues before pushing.
Note: When using local CI configuration,
include:localfiles are also read from your local filesystem. Other include types (components, templates, project files, remote URLs) are always resolved from their remote sources. Jobs frominclude:localfiles are treated as hardcoded by the analysis since they are project-specific and not from reusable external sources.
Custom CI Configuration File Path
Some GitLab projects use a custom CI/CD configuration file instead of the default .gitlab-ci.yml. Plumber auto-detects this from the GitLab project settings, but you can also override it explicitly with the --ci-config-path flag:
# Analyze a project that uses a custom CI file
plumber analyze --ci-config-path my-custom-ci.yml
# Combine with other flags
plumber analyze --gitlab-url https://gitlab.com --project mygroup/myproject --ci-config-path .gitlab/ci/main.yml
In the GitLab CI Component, use the ci_config_path input:
include:
- component: gitlab.com/getplumber/plumber/plumber@v0.1.30
inputs:
ci_config_path: my-custom-ci.yml
💡 Like what you see? Add Plumber to your CI/CD with the GitLab CI Component for automated checks on every pipeline.
Option 2: GitLab CI Component
Add Plumber to your GitLab pipeline: it will run automatically on the default branch, tags and open merge requests.
💬 These instructions are for gitlab.com. Self-hosted? See Self-Hosted GitLab.
Step 1: Create a GitLab Token
- In GitLab, go to User Settings → Access Tokens (or create one here)
- Create a Personal Access Token with
read_api+read_repositoryscopes- Project Access Tokens also work: create one inside your project: Settings → Access Tokens with the same scopes and at least Maintainer role
- Go to your project's Settings → CI/CD → Variables
- Add the token as
GITLAB_TOKEN(masked recommended)
⚠️ Important: The token must belong to a user (or project bot) with Maintainer role (or higher) on the project to access branch protection
