Skip to main content

PipeGuard

Like a linter, but for CI/CD and DevOps mistakes

Python Typer Rich PyYAML Pytest Ruff License: MIT

PipeGuard is a lightweight Python CLI that scans your repository for risky CI/CD workflows, insecure Dockerfiles, and common DevOps configuration mistakes

It helps catch issues such as:

  • Unpinned GitHub Actions
  • Over-permissive workflow tokens
  • Unsafe pull_request_target usage
  • Dangerous curl | bash commands
  • Docker images running as root
  • Dockerfiles using latest tags
  • Missing Docker healthchecks
  • Committed .env files
  • Committed tokens and private keys
  • Unpinned Python dependencies
  • Python packages with known vulnerabilities from pip-audit
  • Docker OS packages that cannot be reliably image-audited

Installation

From the project directory:

pip install -e .

Or install with development tools:

pip install -e ".[dev]"

Built With

Tool Purpose
Python Core language and packaging runtime
Typer Command-line interface for pipeguard scan
Rich Pretty terminal tables and scan reports
PyYAML Workflow and config file parsing
pip-audit Python package vulnerability advisories
Pytest Automated test suite
Ruff Fast Python linting

Usage

Scan the current repository:

pipeguard scan .

Scan a specific repository:

pipeguard scan /path/to/project

Scan a public Git repository:

pipeguard scan https://github.com/owner/repo --ref main

Supported commands

Command Purpose
pipeguard --version Show the installed PipeGuard version
pipeguard scan . Scan the current directory
pipeguard scan <path> Scan a specific project folder
pipeguard scan https://github.com/owner/repo Clone and scan a public Git repository in a temporary directory
pipeguard scan <path> --category cicd Scan only GitHub Actions workflows
pipeguard scan <path> --category docker Scan only Dockerfiles
pipeguard scan <path> --category iac Scan Docker Compose and Kubernetes manifests
pipeguard scan <path> --category repo Scan only repository health checks
pipeguard scan <path> --category secrets Scan only committed secret patterns
pipeguard scan <path> --category vuln Scan dependency and Docker package audit readiness
pipeguard scan <path> --exclude "dist/**" Exclude paths from scanning and reporting
pipeguard scan <path> --docker-image image:tag Scan a Docker image with Trivy or Grype, bootstrapped automatically when missing
pipeguard scan <path> --image-scanner trivy Select the Docker image vulnerability scanner
pipeguard scan <path> --output report.md Export a Markdown report
pipeguard scan <path> --output report.json Export a JSON report
pipeguard scan <path> --output report.sarif Export a SARIF report for code scanning
pipeguard scan <path> --fail-on high Exit with code 1 when high or critical findings exist
pipeguard scan <path> --ignore RULE_ID Ignore a specific rule ID
pipeguard scan <path> --config pipeguard.yml Load a specific PipeGuard config file

Category examples

Scan only GitHub Actions workflows:

pipeguard scan . --category cicd

Scan only Dockerfiles:

pipeguard scan . --category docker

Scan only Docker Compose and Kubernetes manifests:

pipeguard scan . --category iac

Scan only repository health checks:

pipeguard scan . --category repo

Scan only committed secret patterns:

pipeguard scan . --category secrets

Scan only Python package vulnerabilities and Docker package audit readiness:

pipeguard scan . --category vuln

Scan a Docker image with an installed scanner:

pipeguard scan . --category vuln --docker-image python:3.12 --image-scanner auto

When --docker-image is used, PipeGuard first looks for an installed Trivy or Grype binary. If neither is available, it downloads the official scanner installer into a temporary tools directory, runs the scan, and deletes the temporary directory afterward.

Sample output

PipeGuard prints tracking logs, a progress bar, a summary panel, and findings grouped by severity. The examples below are abbreviated from real category scans.

GitHub Actions:

track Scanning GitHub Actions workflows
track Scan complete
Scan complete ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%

PipeGuard Scan Report
Scanned path: /path/to/your-project
Findings: 9 | Critical: 0 | High: 2 | Medium: 7 | Low: 0

HIGH
GH_ACTION_JOB_WRITE_PERMISSION    cicd  .github/workflows/release-tag.yml      24   Job grants write token permissions
GH_ACTION_SECRET_IN_PULL_REQUEST  cicd  .github/workflows/python-security.yml  120  Workflow references secrets in pull request context

MEDIUM
GH_ACTION_UNPINNED_ACTION         cicd  .github/workflows/aws.yml              22   GitHub Action is not pinned to a commit SHA
GH_ACTION_WORKFLOW_WRITE_PERMISSION cicd .github/workflows/tag-codebuild-gated.yml 33 Workflow grants write token permissions

Docker:

track Scanning Dockerfiles
track Scan complete
Scan complete ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%

PipeGuard Scan Report
Scanned path: /path/to/your-project
Findings: 3 | Critical: 0 | High: 0 | Medium: 2 | Low: 1

MEDIUM
DOCKER_LATEST_TAG       docker  side-jobs/delete-junk-provider-redis-queue/Dockerfile  1  Docker image uses latest or implicit latest tag
DOCKER_RUNNING_AS_ROOT  docker  side-jobs/delete-junk-provider-redis-queue/Dockerfile  -  Dockerfile does not switch to a non-root user

LOW
DOCKER_MISSING_HEALTHCHECK docker side-jobs/delete-junk-provider-redis-queue/Dockerfile - Dockerfile does not define a healthcheck

Repository health:

track Scanning repository health
track Scan complete
Scan complete ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%

PipeGuard Scan Report
Scanned path: /path/to/your-project
Findings: 31 | Critical: 0 | High: 0 | Medium: 0 | Low: 31

LOW
REPO_LARGE_FILE             repo  swagger-codegen/swagger-codegen-cli.jar  -   Large file found in repository
REPO_MISSING_ENV_EXAMPLE    repo  .                                        -   Repository is missing .env.example
REPO_REQUIREMENTS_UNPINNED  repo  requirements.txt                         2   Python dependency is not fully pinned

Secrets:

track Scanning committed secret patterns
track Scan complete
Scan complete ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%

PipeGuard Scan Report
Scanned path: /path/to/your-project
Findings: 61 | Critical: 61 | High: 0 | Medium: 0 | Low: 0

CRITICAL
SECRET_AWS_ACCESS_KEY  secrets  app/config.py      25  AWS access key appears to be committed
SECRET_PRIVATE_KEY     secrets  certs/badkey.pem   1   Private key appears to be committed

Vulnerability scan:

track Scanning dependency vulnerabilities
track Collecting Python dependency manifests
track Preparing isolated pip-audit virtual environments
track Virtualenv isolation unavailable, using temporary target directories
track Installing pip-audit into temporary tools directory
track Installing target dependencies from requirements.txt
track Running pip-audit against temporary target directory
track Parsing pip-audit advisory results
track Checking Dockerfile package installs
track Scan complete
Scan complete ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%

PipeGuard Scan Report
Scanned path: /path/to/your-project
Findings: 28 | Critical: 0 | High: 28 | Medium: 0 | Low: 0

HIGH
VULN_PYTHON_PACKAGE_VULNERABLE  vuln  requirements.txt  18  Python package has known vulnerability CVE-2024-37891
VULN_PYTHON_PACKAGE_VULNERABLE  vuln  requirements.txt  28  Python package has known vulnerability CVE-2025-68616

Docker image vulnerability scan:

track Scanning Docker image python:3.9-slim
track Scan complete
Scan complete ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%

PipeGuard Scan Report
Scanned path: /path/to/your-project
Findings: 199 | Critical: 6 | High: 44 | Medium: 85 | Low: 64

CRITICAL
VULN_DOCKER_IMAGE_PACKAGE_VULNERABLE  vuln  python:3.9-slim  -  Docker image package has known vulnerability CVE-2025-15467

HIGH
VULN_DOCKER_IMAGE_PACKAGE_VULNERABLE  vuln  python:3.9-slim  -  Docker image package has known vulnerability CVE-2026-0861

All checks:

track Scanning GitHub Actions workflows
track Scanning Dockerfiles
track Scanning repository health
track Scanning committed secret patterns
track Scanning dependency vulnerabilities
track Scan complete
Scan complete ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100%

PipeGuard Scan Report
Scanned path: /path/to/your-project
Findings: 132 | Critical: 61 | High: 30 | Medium: 9 | Low: 32

Export examples

Export a Markdown report:

pipeguard scan . --output report.md

Export JSON:

pipeguard scan . --output report.json

Export JSON for another project:

pipeguard scan /path/to/flask-app --output flask-app-pipeguard.json

Export SARIF for code scanning:

pipeguard scan . --output pipeguard.sarif

Visible project examples

Scan the bundled unsafe example project:

pipeguard scan examples

Export the bundled unsafe example project to JSON:

pipeguard scan examples --output examples-pipeguard.json

Scan slynk-api:

pipeguard scan /path/to/slynk-api

Export slynk-api to JSON:

pipeguard scan /path/to/slynk-api --output slynk-api-pipeguard.json

Scan Syncraft:

pipeguard scan /path/to/Syncraft

Export Syncraft to JSON:

pipeguard scan /path/to/Syncraft --output syncraft-pipeguard.json

CI and config examples

Fail CI when high-risk issues are found:

pipeguard scan . --fail-on high

Ignore a specific rule:

pipeguard scan . --ignore GH_ACTION_UNPINNED_ACTION

You can also create pipeguard.yml in the repository root:

ignore:
  - GH_ACTION_UNPINNED_ACTION

exclude:
  - examples/**
  - tests/fixtures/**
  - .security-target/**
  - .security-tools/**

fail_on: high

rules:
  DOCKER_MISSING_HEALTHCHECK:
    severity: medium
  REPO_MISSING_ENV_EXAMPLE: off

PipeGuard also looks for pipeguard.yaml, .pipeguard.yml, and .pipeguard.yaml Use --config path/to/file.yml to load a specific config file

See RULES.md for rule IDs, severities, and fixes.

Current checks

GitHub Actions

Rule Severity Description
GH_ACTION_UNPINNED_ACTION Medium Action is pinned to a tag or branch instead of a full SHA
GH_ACTION_MISSING_PERMISSIONS Medium Workflow does not define least-privilege permissions
GH_ACTION_WORKFLOW_WRITE_PERMISSION Medium Workflow grants at least one write token permission
GH_ACTION_WRITE_ALL_PERMISSION High Workflow grants write-all token permissions
GH_ACTION_JOB_WRITE_PERMISSION High Job grants at least one write token permission
GH_ACTION_PULL_REQUEST_TARGET High Workflow uses pull_request_target
GH_ACTION_PULL_REQUEST_TARGET_CHECKOUT_HEAD Critical Workflow appears to use PR head code with pull_request_target
GH_ACTION_SECRET_IN_PULL_REQUEST High Workflow references secrets in pull request context
GH_ACTION_WORKFLOW_RUN_TRIGGER Medium Workflow uses workflow_run trigger
GH_ACTION_CHECKOUT_PERSIST_CREDENTIALS Medium Checkout persists GitHub credentials
GH_ACTION_CURL_BASH High Workflow pipes remote script directly into shell
GH_ACTION_PIP_INSTALL_REMOTE_URL Medium Workflow installs Python package from a remote URL
GH_ACTION_DOCKER_LOGIN_PASSWORD Medium Workflow performs Docker login with a password/secret
GH_ACTION_PYPI_TOKEN_PUBLISH Medium Workflow appears to use a long-lived PyPI token

Dockerfile

Rule Severity Description
DOCKER_LATEST_TAG Medium Base image uses latest or implicit latest tag
DOCKER_RUNNING_AS_ROOT Medium Dockerfile does not switch to non-root user
DOCKER_MISSING_HEALTHCHECK Low Dockerfile does not define a healthcheck
DOCKER_APT_NO_CLEANUP Low apt package lists are not cleaned
DOCKER_COPY_ENTIRE_CONTEXT Low Dockerfile copies the whole context
DOCKER_SECRET_ENV Critical Dockerfile contains a likely secret in ARG/ENV

Docker Compose and Kubernetes

Rule Severity Description
COMPOSE_PRIVILEGED_SERVICE High Compose service runs with privileged mode
COMPOSE_HOST_NETWORK Medium Compose service uses host networking
COMPOSE_RUNS_AS_ROOT Medium Compose service runs as root
K8S_PRIVILEGED_CONTAINER High Kubernetes container runs privileged
K8S_HOST_PATH_VOLUME High Kubernetes workload mounts a hostPath volume
K8S_CONTAINER_RUNS_AS_ROOT Medium Kubernetes container runs as UID 0
K8S_MISSING_RESOURCE_LIMITS Low Kubernetes container is missing resource limits

Repository health

Rule Severity Description
REPO_MISSING_README Low Repository is missing a README
REPO_MISSING_GITIGNORE Low Repository is missing .gitignore
REPO_ENV_FILE_COMMITTED Critical .env style file appears committed
REPO_MISSING_ENV_EXAMPLE Low Repository is missing .env.example
REPO_REQUIREMENTS_UNPINNED Low Python dependency is not fully pinned
REPO_MISSING_PYPROJECT Low Python project may lack modern packaging config
REPO_LARGE_FILE Low Large file found in repository

Vulnerability

Rule Severity Description
VULN_PYTHON_PACKAGE_VULNERABLE High pip-audit reported a known vulnerability for a pinned Python package
VULN_PIP_AUDIT_UNAVAILABLE Medium Isolated pip-audit environment setup or execution failed
VULN_DOCKER_OS_PACKAGE_UNPINNED Medium Dockerfile installs an OS package without an exact version
VULN_DOCKER_IMAGE_PACKAGE_VULNERABLE Low-Critical Trivy or Grype reported a vulnerable package in a Docker image
VULN_DOCKER_IMAGE_SCANNER_UNAVAILABLE Medium Docker image scan was requested but Trivy or Grype could not be found or bootstrapped

Secrets

Rule Severity Description
SECRET_PRIVATE_KEY Critical Private key appears to be committed
SECRET_GITHUB_TOKEN Critical GitHub token appears to be committed
SECRET_AWS_ACCESS_KEY Critical AWS access key appears to be committed
SECRET_STRIPE_KEY Critical Stripe live secret key appears to be committed
SECRET_SLACK_TOKEN High Slack token appears to be committed
SECRET_JWT_TOKEN Medium JWT appears to be committed

Why PipeGuard?

Most teams review application code carefully, but CI/CD workflows, Dockerfiles, and repository setup often receive less attention

PipeGuard gives your repository a quick DevOps health check before small configuration mistakes become production or supply-chain problems

Development

Run tests:

pytest

Run linting:

ruff check .

License

PipeGuard is released under the MIT License

Copyright (c) 2026 Liem Tran

Metadata

Release files for pipeguard-scanner-cli 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pipeguard-scanner-cli 1.0.0
File Size Uploaded
pipeguard_scanner_cli-1.0.0.tar.gz 48.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pipeguard-scanner-cli 1.0.0
File Interpreter ABI Platform
pipeguard_scanner_cli-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 83.4 kB

Release files / pipeguard_scanner_cli-1.0.0.tar.gz

Download URL pipeguard_scanner_cli-1.0.0.tar.gz
Size 48.4 kB
Tags Source
SHA-256 checksum
How to use checksums
12f304d623776ea905e60e2c3b6a9b941bc385edfe43616fa990f831a4c5f448
BLAKE2b-256 checksum
How to use checksums
85d98bc11e1ae279bc0eaab947e58af1386c0cbd2331990d3f045133300ef977
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.13

Release files / pipeguard_scanner_cli-1.0.0-py3-none-any.whl

Download URL pipeguard_scanner_cli-1.0.0-py3-none-any.whl
Size 35.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8b1ee285f8e64a7a0d8a2d0aa48160391a8bae0533e19e35d57601471a606727
BLAKE2b-256 checksum
How to use checksums
0e65fb342dce2bd44c8d97baeab8a58c3ba6bf641f602cf037b26be35073f0f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.13

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page