Like a linter, but for CI/CD and DevOps mistakes.
Project description
PipeGuard
Like a linter, but for CI/CD and DevOps mistakes
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_targetusage - Dangerous
curl | bashcommands - Docker images running as root
- Dockerfiles using
latesttags - Missing Docker healthchecks
- Committed
.envfiles - 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 |
|---|---|
| Core language and packaging runtime | |
Command-line interface for pipeguard scan |
|
| Pretty terminal tables and scan reports | |
| Workflow and config file parsing | |
pip-audit |
Python package vulnerability advisories |
| Automated test suite | |
| 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12f304d623776ea905e60e2c3b6a9b941bc385edfe43616fa990f831a4c5f448
|
|
| MD5 |
a92055c3966df1360617315c3243b6c9
|
|
| BLAKE2b-256 |
85d98bc11e1ae279bc0eaab947e58af1386c0cbd2331990d3f045133300ef977
|
File details
Details for the file pipeguard_scanner_cli-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pipeguard_scanner_cli-1.0.0-py3-none-any.whl
- Upload date:
- Size: 35.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b1ee285f8e64a7a0d8a2d0aa48160391a8bae0533e19e35d57601471a606727
|
|
| MD5 |
57cf96b423c42f045b71880a73ab3cbc
|
|
| BLAKE2b-256 |
0e65fb342dce2bd44c8d97baeab8a58c3ba6bf641f602cf037b26be35073f0f4
|