Skip to main content

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

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pipeguard_scanner_cli-1.0.0.tar.gz (48.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pipeguard_scanner_cli-1.0.0-py3-none-any.whl (35.0 kB view details)

Uploaded Python 3

File details

Details for the file pipeguard_scanner_cli-1.0.0.tar.gz.

File metadata

  • Download URL: pipeguard_scanner_cli-1.0.0.tar.gz
  • Upload date:
  • Size: 48.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for pipeguard_scanner_cli-1.0.0.tar.gz
Algorithm Hash digest
SHA256 12f304d623776ea905e60e2c3b6a9b941bc385edfe43616fa990f831a4c5f448
MD5 a92055c3966df1360617315c3243b6c9
BLAKE2b-256 85d98bc11e1ae279bc0eaab947e58af1386c0cbd2331990d3f045133300ef977

See more details on using hashes here.

File details

Details for the file pipeguard_scanner_cli-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pipeguard_scanner_cli-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8b1ee285f8e64a7a0d8a2d0aa48160391a8bae0533e19e35d57601471a606727
MD5 57cf96b423c42f045b71880a73ab3cbc
BLAKE2b-256 0e65fb342dce2bd44c8d97baeab8a58c3ba6bf641f602cf037b26be35073f0f4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page