Help us shape the future of Go! Take the 2026 Go Developer Survey

plumber

command module
v0.7.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2026 License: MPL-2.0 Imports: 1 Imported by: 0

README

Plumber

Plumber Score OpenSSF Scorecard SLSA 3 Latest Release Docker Pulls

CI/CD security scanner for GitHub Actions and GitLab CI

Securing the workflows of:

Resty
Resty
★ 11.8k
nginx-ui
nginx-ui
★ 11.5k
Lightpanda
Lightpanda
★ 36k
Delve
Delve
★ 24.9k
Duplicati
Duplicati
★ 15k
Bunkerity
Bunkerity
★ 11k
Stellarium
Stellarium
★ 10k
intuitem
intuitem
★ 4.4k
Outscale
Outscale
★  
Telstra
Telstra
★  

📡 Plumber Radar ➡️ 20k public repos scanned


What is Plumber?

Plumber scans CI/CD pipelines for risky patterns and security gaps.

  • GitHub Actions: scans .github/workflows/*.{yml,yaml} and repository settings.
  • GitLab CI: scans .gitlab-ci.yml, resolved includes, and repository settings.

Findings are reported in the terminal, JSON, SARIF, GitLab SAST, CSV, OCSF, PBOM, and CycloneDX.

plumber analyze scanning a repository

Where to run it

Use it for
💻 Run locally Trying Plumber, or auditing repos from a script
🐙 Run in GitHub Actions Checks on every PR and push, findings in Code Scanning
🦊 Run in GitLab CI Checks on every pipeline, findings in the MR widget

Quick start

brew tap getplumber/plumber
brew trust --formula getplumber/plumber/plumber
brew install plumber

plumber analyze

No config file is needed: plumber analyze runs with the built-in default configuration (defaultConfig/.plumber.yaml) and auto-detects the provider from your git remote.

Install

Other options besides Homebrew:

Upgrade

brew upgrade plumber
# or
mise upgrade github:getplumber/plumber

A mise use install pins the version it resolved at install time, so an upgrade is an explicit step. mise also ignores a release younger than 24 hours by default (minimum_release_age), so a release of the day arrives the next day unless you set MISE_MINIMUM_RELEASE_AGE=0. plumber version prints an upgrade notice, with the command for your install, whenever a newer release exists.

Authenticate

# GitHub, using the gh CLI keyring
gh auth login
# or, for CI runners and automation
export GH_TOKEN=ghp_xxxx

# GitLab
export GITLAB_TOKEN=glpat_xxxx

Run

# current repo
plumber analyze

# a GitHub repo without a local clone
plumber analyze github.com/owner/repo

# a GitLab project without a local clone (self-hosted instances work too)
plumber analyze gitlab.com/group/project

The target can also be a full URL pasted from the browser (https://github.com/owner/repo/tree/main selects the branch). Run plumber analyze --help for the full flag list.

GitHub Action

Add the official Plumber action to .github/workflows/plumber.yml:

name: Plumber

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read
  actions: read # lets Plumber read workflow states and one run log to prove the token scope
  security-events: write
  id-token: write # required by score-push

jobs:
  plumber:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6
      - uses: getplumber/plumber@<version>
        with:
          # Publishes your Plumber Score and repository name publicly on
          # score.getplumber.io (see Score badge below). Set to false to keep them private.
          score-push: true

Full guide: getplumber.io/docs/cli/github#run-with-github-actions

GitLab CI component

Add the official Plumber component to .gitlab-ci.yml:

include:
  - component: gitlab.com/getplumber/plumber/plumber@<version>
    inputs:
      # Publishes your Plumber Score and repository name publicly on
      # score.getplumber.io (see Score badge below). Set to false to keep them private.
      score_push: true

Add GITLAB_TOKEN in Settings -> CI/CD -> Variables: plumber environment, read_api + read_repository for scanning, or api if you want Plumber to post MR comments or badges.

Full guide: getplumber.io/docs/cli/gitlab#run-with-the-gitlab-ci-component

Self-hosted GitLab: host or mirror the component in your instance and include that URL. Guide.

Score badge

The score follows attack paths, not issue counts: see the scoring docs.

The badge at the top of this README comes from the hosted score service. With score push on (score-push: true on the Action, score_push: true on the component, as in the snippets above), each run on the default branch keeps an A-E badge for your repo up to date:

[![Plumber Score](https://score.getplumber.io/github.com/OWNER/REPO.svg)](https://score.getplumber.io/github.com/OWNER/REPO)

For a GitLab project, use gitlab.com/GROUP/PROJECT in place of github.com/OWNER/REPO.

Score push makes your score and repository name public, works in CI only, and is off by default when the input is omitted. See the score docs.

Configuration

Plumber reads .plumber.yaml; without one, the built-in default applies.

plumber config init       # create one interactively
plumber config generate   # write the full commented default template
plumber config validate
plumber capabilities defaults   # print the built-in capability list, ready to copy and narrow
plumber explain ISSUE-411

Example:

version: "2.0"

github:
  controls:
    actionsMustBePinnedByCommitSha:
      enabled: true
      trustedOwners:
        - actions
        - github

gitlab:
  controls:
    containerImageMustNotUseForbiddenTags:
      enabled: true

Extend the baseline with extends: plumber:default and list only what you change; new controls Plumber ships then appear automatically. Full reference: defaultConfig/.plumber.yaml and getplumber.io/docs/cli.

Controls

A few of the checks Plumber runs:

  • Unpinned actions and images: a third-party action or container image referenced by a tag that can be moved to other code.
  • Remote scripts piped into a shell: curl | bash and similar, running code nobody reviewed.
  • Unprotected default branch: anyone with push access can change what gets built and released.
  • See all controls

Outputs

Output Flag Use it for
Terminal default Human review during local or CI runs
JSON --output results.json Automation and dashboards
SARIF --sarif results.sarif GitHub Code Scanning and SARIF tools
GitLab SAST --glsast gl-sast-report.json GitLab Security Dashboard / MR widget
CSV --csv results.csv Spreadsheets, ad-hoc analysis
OCSF --ocsf plumber.ocsf.json OCSF consumers and GRC platforms
PBOM --pbom pbom.json Pipeline inventory
CycloneDX --pbom-cyclonedx cdx.json SBOM tooling

Exit codes

Code Meaning
0 Score meets the gate (--min-points / --min-score), or --no-controls was used and collection succeeded
1 Score is below the gate
2 Invalid usage or configuration, or a runtime / provider / auth / network failure
3 Data collection was incomplete, so the score is withheld; or a check could not be verified and --fail-warnings is set (e.g. an action version that could not be resolved)

Contributing

make build
make test

Contributing guide: CONTRIBUTING.md

Resources

License

Plumber is licensed under the Mozilla Public License 2.0.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
Package capability recognizes what a pipeline job does from the facts the CLI already parsed (the job's image, the include that defined it, its report artifacts, its script lines) and from the wrapper scripts it calls in the checkout.
Package capability recognizes what a pipeline job does from the facts the CLI already parsed (the job's image, the include that defined it, its report artifacts, its script lines) and from the wrapper scripts it calls in the checkout.
capdecl
Package capdecl holds the pipeline capability declaration schema: the types a user (or the CLI's own built-in list) writes a capability in, their strict decode from YAML and tolerant decode from JSON, the bounds that make a declared list safe to compile and to store, and the bounded glob matcher its patterns compile to (spec sections 4.2, 4.3 and 4.6 of the pipeline capabilities design, revised 2026-10-17, in the Plumber monorepo).
Package capdecl holds the pipeline capability declaration schema: the types a user (or the CLI's own built-in list) writes a capability in, their strict decode from YAML and tolerant decode from JSON, the bounds that make a declared list safe to compile and to store, and the bounded glob matcher its patterns compile to (spec sections 4.2, 4.3 and 4.6 of the pipeline capabilities design, revised 2026-10-17, in the Plumber monorepo).
Package cmd is the Plumber command line: the cobra commands (analyze, config, explain, catalog, version), the provider dispatch between the GitLab and GitHub analysis paths, terminal rendering, and every output writer (results JSON, SARIF, GitLab SAST, OCSF, CSV, PBOM) plus the platform push.
Package cmd is the Plumber command line: the cobra commands (analyze, config, explain, catalog, version), the provider dispatch between the GitLab and GitHub analysis paths, terminal rendering, and every output writer (results JSON, SARIF, GitLab SAST, OCSF, CSV, PBOM) plus the platform push.
Package configuration owns .plumber.yaml: the typed control configuration structs, loading with unknown-key validation and the v1 to v2 conversion, the overlay merge over the shipped default, the required-components expression parser, the control registry (ids, categories, providers) and the reflected config schema the platform renders forms from.
Package configuration owns .plumber.yaml: the typed control configuration structs, loading with unknown-key validation and the v1 to v2 conversion, the overlay merge over the shipped default, the required-components expression parser, the control registry (ids, categories, providers) and the reflected config schema the platform renders forms from.
Package control runs an analysis end to end: it drives the provider data collections, projects the collected data and the user's configuration onto the Rego engine input, evaluates the policies, and turns findings into per-control statuses, the Plumber score, and the catalog of controls and issue codes that every other consumer (the terminal, the outputs, the platform) reads from.
Package control runs an analysis end to end: it drives the provider data collections, projects the collected data and the user's configuration onto the Rego engine input, evaluates the policies, and turns findings into per-control statuses, the Plumber score, and the catalog of controls and issue codes that every other consumer (the terminal, the outputs, the platform) reads from.
Package defaultConfig embeds the CLI's shipped .plumber.yaml, the baseline every zero-config run and every `extends: plumber:default` overlay starts from.
Package defaultConfig embeds the CLI's shipped .plumber.yaml, the baseline every zero-config run and every `extends: plumber:default` overlay starts from.
finding
identity
Package identity computes the stable identity of a finding: the recipe (versioned by RecipeVersion) that turns a finding's code, subject and configuration into the hash the platform tracks an issue by across runs.
Package identity computes the stable identity of a finding: the recipe (versioned by RecipeVersion) that turns a finding's code, subject and configuration into the hash the platform tracks an issue by across runs.
Package github is the GitHub provider: the workflow parser over .github/workflows, the action metadata client that resolves `uses:` refs against the GitHub API, branch protection and ruleset reads, and the intermediate-representation builder the Rego policies evaluate.
Package github is the GitHub provider: the workflow parser over .github/workflows, the action metadata client that resolves `uses:` refs against the GitHub API, branch protection and ruleset reads, and the intermediate-representation builder the Rego policies evaluate.
Package gitlab is the GitLab provider: the API clients (REST and GraphQL), the data collections over a project (CI configuration and its includes, images, branch protection, approvals, CI/CD variables, security policy), the intermediate-representation builder those collections feed, and the merge-request comment and badge writers.
Package gitlab is the GitLab provider: the API clients (REST and GraphQL), the data collections over a project (CI configuration and its includes, images, branch protection, approvals, CI/CD variables, security policy), the intermediate-representation builder those collections feed, and the merge-request comment and badge writers.
internal
cidigest
Package cidigest computes the CI config content digest the platform and the CLI compare to decide whether a branch may reuse the platform snapshot's resolved config: a content-keyed (not branch-keyed) identity for a project's CI config, made of the root file plus every LOCAL include statically reachable from it.
Package cidigest computes the CI config content digest the platform and the CLI compare to decide whether a branch may reuse the platform snapshot's resolved config: a content-keyed (not branch-keyed) identity for a project's CI config, made of the root file plus every LOCAL include statically reachable from it.
engine/opa
Package opa hosts the Rego engine: it compiles the embedded policies, evaluates them over the intermediate representation and the projected configuration, and returns findings with their source locations.
Package opa hosts the Rego engine: it compiles the embedded policies, evaluates them over the intermediate representation and the projected configuration, and returns findings with their source locations.
expr
Package expr evaluates GitHub Actions style `if:` conditions under three-valued logic.
Package expr evaluates GitHub Actions style `if:` conditions under three-valued logic.
ir
Package ir is the provider-neutral intermediate representation of a pipeline: jobs, images, includes, branches, variables and settings in the one shape every Rego policy reads, built by the gitlab and github packages.
Package ir is the provider-neutral intermediate representation of a pipeline: jobs, images, includes, branches, variables and settings in the one shape every Rego policy reads, built by the gitlab and github packages.
platform
Package platform is the CLI side of the platform link: the /context read that a linked run starts from (policies, snapshot lanes, dismissals), the run context that records what the platform served, and the HTTP client with its OIDC token exchange.
Package platform is the CLI side of the platform link: the /context read that a linked run starts from (policies, snapshot lanes, dismissals), the run context that records what the platform served, and the HTTP client with its OIDC token exchange.
runcache
Package runcache keeps the JSON report of the last analysis of each project in the user cache directory, so a later command can read it back without running the analysis again.
Package runcache keeps the JSON report of the last analysis of each project in the user cache directory, so a later command can read it back without running the analysis again.
runners
This file names the command-line tools GitHub's own hosted runner images ship by default, per image: a download a workflow only reaches when that tool is absent (a `command -v X ||` guard and the like) never runs at all on a runner where X is already on PATH.
This file names the command-line tools GitHub's own hosted runner images ship by default, per image: a download a workflow only reaches when that tool is absent (a `command -v X ||` guard and the like) never runs at all on a runner where X is already on PATH.
testsupport/pipelines
Package pipelines builds ir.NormalizedPipeline values from CI files for tests, so the controls' tests, the situation tests and the control package's corpus share one reading of the YAML instead of three copies.
Package pipelines builds ir.NormalizedPipeline values from CI files for tests, so the controls' tests, the situation tests and the control package's corpus share one reading of the YAML instead of three copies.
Package pbom generates the Pipeline Bill of Materials: the CycloneDX and native documents that inventory a pipeline's includes, components, images and actions together with their compliance verdicts.
Package pbom generates the Pipeline Bill of Materials: the CycloneDX and native documents that inventory a pipeline's includes, components, images and actions together with their compliance verdicts.
Package policies embeds the Rego policies, one file per control, that the engine evaluates over the intermediate representation.
Package policies embeds the Rego policies, one file per control, that the engine evaluates over the intermediate representation.
lib
Package lib embeds the Rego library every policy module is compiled with (monorepo spec 2026-10-16 section 5: one shared provenance helper).
Package lib embeds the Rego library every policy module is compiled with (monorepo spec 2026-10-16 section 5: one shared provenance helper).
situation
Package situation embeds the Rego module that derives per-job situation facts (triggers, privilege, impact) from the normalized pipeline.
Package situation embeds the Rego module that derives per-job situation facts (triggers, privilege, impact) from the normalized pipeline.
Package provider is the seam between the command line and the two analysis paths: one Provider implementation per git host (GitLab, GitHub) answers how to run the analysis, compute compliance, write the PBOM and perform the post-analysis actions, so the cmd package never branches on the provider name itself.
Package provider is the seam between the command line and the two analysis paths: one Provider implementation per git host (GitLab, GitHub) answers how to run the analysis, compute compliance, write the PBOM and perform the post-analysis actions, so the cmd package never branches on the provider name itself.
Package utils holds the small provider-neutral helpers shared across the CLI: git remote detection and parsing, bounded file reads, FNV hashing, and container image reference normalization.
Package utils holds the small provider-neutral helpers shared across the CLI: git remote detection and parsing, bounded file reads, FNV hashing, and container image reference normalization.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL