Plumber checks your CI/CD configuration and project settings against a catalog of controls. The catalog is split per provider: GitLab controls inspect .gitlab-ci.yml and GitLab project settings, GitHub controls inspect .github/workflows/*.yml and GitHub repository settings. Pick the provider tab below to see the relevant catalog.
When a control is not respected, an issue is created. Click the ISSUE-XXX link in any row to see the full description, impact, and remediation for that issue.
Scope
- All: Plumber Platform and Open Source CLI
- Platform: Plumber Platform only
- CLI: Open Source CLI only (not a Platform control)
| Scope | Control | What it checks | Why it matters |
|---|
| All | Container images must come from authorized sources ISSUE-101 | Verifies that container images used to run your CI/CD pipelines come from authorized and trusted sources. | Helps mitigate security risks introduced by the use of malicious, compromised, or vulnerable images. |
| All | Container images must not use forbidden tags ISSUE-102 | Verifies that container images used to run your CI/CD pipelines rely on authorized tags. | Helps mitigate both security and functional risks introduced by the use of unverified, outdated, or compromised image versions. |
| CLI | Container images must be pinned by digest ISSUE-103 | Verifies that container images are referenced by their SHA256 digest rather than a mutable tag. | Prevents supply chain attacks where a tag is overwritten with a compromised image, guaranteeing exact image content in every pipeline run. |
| Scope | Control | What it checks | Why it matters |
|---|
| Platform | CI/CD variables must be protected ISSUE-201 | Verifies that CI/CD variables used in a project have the protected field enabled. | Ensures sensitive values are restricted to protected branches or tags, reducing unauthorized exposure. |
| Platform | CI/CD variables must be masked ISSUE-202 | Verifies that CI/CD variables used in a project have the masked field enabled. | Prevents variable values from being exposed in pipeline logs, reducing the risk of leaks. |
| CLI | Pipeline must not enable debug trace ISSUE-203 | Verifies that CI_DEBUG_TRACE and CI_DEBUG_SERVICES are not enabled in the pipeline configuration. | Prevents exposure of all CI/CD variable values in job logs, including secrets and tokens. |
| CLI | Pipeline must not use unsafe variable expansion ISSUE-204 | Detects user-controlled CI variables expanded in shell re-interpretation contexts (eval, sh -c, bash -c, source). | Prevents command injection via crafted branch names, MR titles, or commit messages (OWASP CICD-SEC-1). |
| CLI | Pipeline must not override job variables ISSUE-205 | Detects controlled CI/CD variables redefined in .gitlab-ci.yml that should only be set in GitLab CI/CD Settings. | Reduces risk of tampering with scanner settings or other governed variables via pipeline YAML. |
| Scope | Control | What it checks | Why it matters |
|---|
| CLI | Pipeline must not leak secrets in configuration ISSUE-301 | Pipes the resolved .gitlab-ci.yml (with all include:s merged) through gitleaks. Any high-confidence match against the built-in or a custom rule set surfaces as a Critical finding with the secret value redacted to first/last 4 chars. | Catches the most common credential-leak path (someone pastes a token into the YAML “just to test”). Detection is opt-in because gitleaks must be installed separately; once enabled, redaction guarantees the raw secret never reaches the JSON report. |
| Scope | Control | What it checks | Why it matters |
|---|
| All | Pipelines must include templates ISSUE-405 ISSUE-406 | Verifies that the projects contain specific templates. This control can also allow overriding certain variables in the included templates. | Ensures pipelines comply with required security and compliance practices. |
| All | Pipelines must include components ISSUE-408 ISSUE-409 | Verifies that the projects contain specific GitLab components. This control can also allow overriding certain variables in the included components. | Ensures pipelines integrate mandatory security and compliance steps. |
| Platform | Pipeline must include required phases ISSUE-407 | Verifies that the CI/CD pipeline includes a group of job types. | Ensures completeness and compliance of the pipeline execution flow. |
| All | Pipeline must not contain hardcoded jobs ISSUE-401 | Verifies that no hardcoded job is used in CI/CD pipelines. | Improves maintainability and ensures compliance with best practices. |
| All | Pipeline must not use forbidden ref in includes ISSUE-404 | Verifies that the included refs are using specified tags. | Prevents reliance on insecure or non-compliant references. |
| All | Pipeline must use only up-to-date includes ISSUE-403 | Verifies that the included pipelines are up-to-date compared to their source. | Reduces risks from outdated or vulnerable templates. |
| CLI | Security jobs must not be weakened ISSUE-410 | Detects security scanning jobs (SAST, Secret Detection, Container Scanning, etc.) weakened by allow_failure: true, rules: overrides with when: never / when: manual, or when: manual at job level. | Prevents silently neutralized security scans that give a false sense of compliance (OWASP CICD-SEC-4). |
| CLI | Pipeline must not execute unverified scripts ISSUE-411 | Detects jobs that download and immediately execute scripts from the internet (curl | bash, wget | sh, download-then-execute) without integrity verification. | Prevents supply chain attacks where a compromised URL serves a modified script that exfiltrates secrets (OWASP CICD-SEC-3, CICD-SEC-8). |
| CLI | Pipeline must not use Docker-in-Docker ISSUE-412 ISSUE-413 | Detects Docker-in-Docker (docker:dind) services and insecure daemon configuration (for example plaintext Docker API). | Reduces container escape and lateral movement risk on shared runners; prefer Kaniko or Buildah for image builds. |
| Scope | Control | What it checks | Why it matters |
|---|
| All | Branch must be protected ISSUE-501 ISSUE-505 | Verifies that the project configuration respects the protection, push, merge and owner approval on included branch names. | Prevents unauthorized modifications and enforces branch protection standards. |
| Platform | MR approval rules must have at least N approval required ISSUE-502 | Verifies that the project merge request approval rules that cover all protected branches have a minimum number of approval requirements. | Prevents unreviewed code from being merged, reducing security risks. |
| Platform | MR approval settings must be compliant ISSUE-503 | Verifies that MR approval settings are properly configured. | Ensures compliance with review and security requirements. |
| Platform | An MR approval rule must be defined to cover all protected branches ISSUE-504 | Verifies that the protected branches have at least one approval rule. | Ensures protected branches cannot bypass review processes. |
| Platform | MR settings must be compliant ISSUE-506 | Verifies that the project’s merge request settings are correct in terms of merge method, resolving differences, squashing, etc. | Reduces risk of unauthorized or insecure code changes. |
| Platform | Number of project members must respect a quota ISSUE-507 | Verifies that the project configuration respects the owner, maintainer and developer quotas. | Prevents uncontrolled access that could weaken project security. |
| Platform | Number of group members must respect a quota ISSUE-508 | Verifies that the group configuration respects the owner, maintainer and developer quotas. | Prevents uncontrolled access at group level, strengthening governance. |
| Scope | Control | What it checks | Why it matters |
|---|
| Platform | Project must have a security policy source ISSUE-601 | Verifies if the projects have a specific project as their source of security policy. | Ensures compliance with security policy and reduces risk of unmanaged vulnerabilities. |
GitHub Actions support is currently Open Source CLI only.
All controls below carry the CLI badge. Plumber Platform does not scan GitHub Actions workflows yet; Platform GitHub support follows in a later release.
What Plumber scans (GitHub CLI)
- Source: committed files under
.github/workflows/ in the analyzed ref (local clone or remote fetch). - Static YAML only: no org/repo Variables, no runtime
$GITHUB_ENV writes, no evaluation of GitHub expression syntax in values. - Step
uses: third-party owner/repo@ref actions (ISSUE-702/703). Not local ./.github/actions/*, not job-level reusable-workflow uses:, not nested actions inside composites. - API-backed rules (ISSUE-702, ISSUE-703): need
gh auth login or GH_TOKEN. Without auth they abstain (no finding, not a pass).
| Scope | Control | What it checks | Why it matters |
|---|
| All | Container images must not use forbidden tags ISSUE-102 | Same forbidden-tag policy (latest, dev, …), applied to GitHub Actions container references. With the embedded option containerImagesMustBePinnedByDigest: true, any non-digest reference also fails. | Mutable tags create non-reproducible builds and a path for surprise upgrades. |
| Scope | Control | What it checks | Why it matters |
|---|
| CLI | Pipeline must not enable debug trace ISSUE-203 | Static env: (workflow/job/step, merged per job): truthy literals plus GitHub expressions on forbidden names. Also run: lines that write forbidden names to $GITHUB_ENV. | Debug toggles dump masked secrets into logs. Org/repo Variables with no YAML reference and UI “Re-run with debug logging” remain out of scope. |
| CLI | Workflow must not inline user input into shell scripts ISSUE-207 | Detects ${{ github.event.* }} expressions inlined directly into run: shell scripts. | Workflow template-injection is the GitHub Actions equivalent of SQL injection: the PR title or branch name becomes part of the executed shell command. |
| Scope | Control | What it checks | Why it matters |
|---|
| CLI | Reusable workflow must not use secrets: inherit ISSUE-302 | Flags callers that pass secrets: inherit instead of declaring the secrets the callee needs. | Inheriting hands every caller secret to the reusable workflow — a third-party reusable workflow then sees secrets it should never see. |
| Scope | Control | What it checks | Why it matters |
|---|
| CLI | Security jobs must not be weakened ISSUE-410 | Detects security scanning jobs neutralized by continue-on-error: true, narrow if: conditions, or always-skip triggers. | Same OWASP CICD-SEC-4 pattern as on GitLab — a green pipeline that secretly skipped its security scan is worse than no scan. |
| CLI | Workflow must not use Docker-in-Docker ISSUE-412 ISSUE-413 | Detects DinD service usage and insecure daemon configuration in workflow jobs. | Container escape and lateral movement risk applies to self-hosted runners the same way it does to GitLab shared runners. |
| CLI | Workflows must include required actions ISSUE-417 | Asserts that every workflow file under .github/workflows/ collectively references a configured set of required actions or reusable workflows. Step-level uses: and job-level reusable-workflow uses: both count. Matching is ref-agnostic with a slash-guard against accidental prefix collisions. | Closes the gap between an org-wide policy that says “every repo runs the security suite” and a per-repo workflow that quietly dropped the uses: line. Disabled by default; opt in once the required action set is settled. |
| Scope | Control | What it checks | Why it matters |
|---|
| All | Branch must be protected ISSUE-501 ISSUE-505 | Reads both classic Branch Protection and any Repository or Organization Ruleset covering the branch. Verifies required reviews, force-push prevention, code-owner approval, and status checks against the merged effective configuration (stricter wins). | Prevents direct push and force-push attacks on protected refs even when half the protection lives in classic Branch Protection and the other half in a Ruleset. |
| Scope | Control | What it checks | Why it matters |
|---|
| CLI | Third-party actions must be pinned by commit SHA ISSUE-701 | Verifies every uses: owner/repo@ref is pinned by a 40-character commit SHA, not a mutable tag or branch. | Defends against the March 2025 tj-actions / reviewdog supply chain compromise pattern (CVE-2025-30066), where attackers retag actions to point at malicious code that then runs with the caller’s secrets. |
| CLI | Actions must not reference archived repositories ISSUE-702 | Step-level uses: owner/repo@ref in committed workflows. Queries GitHub for archived: true (one cached API call per owner/repo). Requires gh / GH_TOKEN; abstains without auth. | Archived repos stop receiving patches. Does not inspect reusable-workflow callees, local actions, or runtime installs. PBOM: archived: true. |
| CLI | Actions must not carry known CVEs ISSUE-703 | Same step-level uses: scope as ISSUE-702. Queries GitHub Advisory Database (actions ecosystem); semver-filters by vulnerable_version_range when the ref is a tag. SHA pins without a resolvable tag may match conservatively. | Catches known-vulnerable action versions (e.g. tj-actions CVE-2025-30066). Requires API auth; abstains without it. PBOM: hasCve + advisories: [GHSA-…]. |
| Scope | Control | What it checks | Why it matters |
|---|
| CLI | Workflow permissions must be declared ISSUE-801 | Flags workflows that omit a top-level permissions: block, relying on the repo’s default GITHUB_TOKEN permissions. | Implicit permissions default to whatever the repo / org allows, often write-all. Explicit minimum scopes shrink blast radius on a token leak. |
| CLI | Workflow must not subscribe to dangerous triggers ISSUE-802 | Flags workflows triggered by pull_request_target or workflow_run. | These triggers grant secret access to PR-author-controlled code paths. They are the root cause behind the highest-impact GitHub Actions CVEs of the last two years. |
| CLI | Workflow must not grant write-all permissions ISSUE-803 | Static permissions: in workflow YAML. Flags only the literal shortcut write-all (workflow-level propagates to every job). Not read-all, not scope maps like contents: write, not missing blocks (ISSUE-801). | write-all grants every GITHUB_TOKEN scope at once. Pair with ISSUE-801 for jobs with no explicit block. |