Skip to main content

Pre-commit security scanner for GitHub Actions workflows

Project description

PipeGuard

CI PyPI Version Downloads License

PipeGuard

Catch GitHub Actions security issues before they reach your runners.

Pre-commit security scanner for GitHub Actions workflows. Catches supply-chain risks, unpinned actions, known CVEs, and secret leaks — before you push.


Demo

Demo

The recording shows a scan of a real workflow file with multiple security issues. PipeGuard detects them all in under a second — no API key, no network call, fully offline:

  • No top-level permissions: block — GitHub grants write access to all scopes by default
  • tj-actions/changed-files@v35 and reviewdog/action-setup@v1 match known CVEs in the bundled database
  • All actions are pinned to tags instead of commit SHAs — a supply-chain risk
  • echo ${{ secrets.DEPLOY_TOKEN }} leaks a secret value to the workflow log
  • 8398a7/action-slack is a third-party action from an unverified publisher

PipeGuard vs. the alternatives

Feature PipeGuard actionlint StepSecurity act
SHA-pinning check
CVE database (offline) ✅ (online)
Permissions analysis ⚠️ syntax only
Secrets-leak detection ✅ (runtime)
Supply-chain audit
Syntax / type checks ✅ via actionlint
Run workflows locally
Runtime hardening
Pre-commit hook
SARIF output
No API key required
Fully offline ⚠️ needs images
Open source
Free ✅ core ⚠️ freemium

PipeGuard fills the gap between authoring and execution: static security analysis, offline, before you push, without any external service.


Installation

Prerequisites: Python 3.11+

pip install pipeguard-cli

Install actionlint (required for syntax checks, optional for other checks):

# Linux
curl -fsSL https://github.com/rhysd/actionlint/releases/latest/download/actionlint_linux_amd64.tar.gz \
  | tar xz actionlint && sudo mv actionlint /usr/local/bin/

# macOS
brew install actionlint

# Ubuntu/Debian (snap)
sudo snap install actionlint

Usage

pipeguard scan [PATH]

PATH can be a single workflow file or a directory. If omitted, defaults to .github/workflows.

Examples

# Scan entire .github/workflows directory (default)
pipeguard scan

# Scan a specific directory
pipeguard scan .github/workflows/

# Scan a single file
pipeguard scan .github/workflows/ci.yml

# JSON output (for scripts / CI pipelines)
pipeguard scan --format json

# SARIF output (for IDE integration, GitHub Code Scanning)
pipeguard scan --format sarif

# Use a custom config file
pipeguard scan --config path/to/.pipeguard.yml

When scanning a directory, pipeguard prints a per-file header and a summary at the end:

Scanning: .github/workflows/ci.yml
  ✓ No issues found

Scanning: .github/workflows/deploy.yml
  ╭─────────┬──────────────────┬──────────────────────────┬──────────────╮
  │ Severity│ Rule             │ Location                 │ Message      │
  ├─────────┼──────────────────┼──────────────────────────┼──────────────┤
  │ error   │ cve-cve-2025-... │ deploy.yml:12            │ Action ...   │
  │ error   │ sha-pinning      │ deploy.yml:15            │ Action ...   │
  ╰─────────┴──────────────────┴──────────────────────────┴──────────────╯

Scanned 2 file(s) — 2 error(s), 1 warning(s), 3 info(s) total.

Exit codes

Code Meaning
0 No errors or warnings
1 One or more errors or warnings found

Info-level findings (action inventory) do not affect the exit code.


Security checks

Errors & Warnings

Rule Severity Description
sha-pinning error Action pinned to a tag or branch instead of a full commit SHA — supply-chain risk (cf. CVE-2025-30066)
sha-pinning-reusable error Reusable workflow called with a tag or branch ref instead of a full commit SHA — same supply-chain risk as unpinned actions
cve-<id> error Action matches a known CVE in the local database (offline, no API)
supply-chain warning Third-party action from an unverified publisher — suppress per publisher or action via .pipeguard.yml
secrets-leak error Secret value echoed or logged in a run: step
secrets-leak-debug error / warning set -x or set -o xtrace in a run: step — shell debug mode prints every expanded command; error when secrets are in env scope, warning otherwise
permissions-missing error No permissions: block — GitHub grants write access to most scopes by default
permissions-write-all error permissions: write-all at top-level or per-job
permissions-excessive warning Sensitive scope (e.g. secrets, workflows) set to write
permissions-id-token-unused warning id-token: write is set but no OIDC-consuming action is present — allows minting cloud credentials unnecessarily
permissions-invalid error Unknown permission level (not read, write, or none)
pull-request-target warning pull_request_target trigger runs with base-repo write permissions and secret access — even for fork PRs
pull-request-target-pwn error pull_request_target combined with checkout of the PR head ref — allows untrusted fork code to run with secrets (Pwn Request)
actionlint error Syntax and type errors (requires actionlint)

Info

Rule Severity Description
action-inventory info Inventory of all third-party actions used — ref(s) and occurrence count

CVE database

PipeGuard ships with a built-in offline CVE database — no API key, no network call during scan. The database is updated daily via NVD and shipped with each new weekly release.

[!NOTE] Last updated: 2026-03-12

CVE Action Description
CVE-2025-30066 tj-actions/changed-files tj-actions/changed-files was compromised in a supply-chain attack. All tag-based refs are potentially affected — pin to a known-good SHA.
CVE-2025-30154 reviewdog/action-setup reviewdog/action-setup was compromised in the same supply-chain campaign as tj-actions/changed-files. Pin to a vetted SHA.
CVE-2023-49291 tj-actions/branch-names tj-actions/branch-names improperly references github.event.pull_request.head.ref and github.head_ref in a run step, allowing a specially crafted branch name to execute arbitrary code and steal secrets or abuse GITHUB_TOKEN permissions.

SHA-pinned refs are not flagged — another reason to always pin to a commit SHA.

To get the latest CVEs, upgrade to the newest release:

pip install --upgrade pipeguard-cli

Configuration

PipeGuard looks for a .pipeguard.yml (or .pipeguard.yaml, pipeguard.yml, pipeguard.yaml) in the current directory and its parents.

Suppress supply-chain warnings for trusted publishers

If you trust a specific publisher or action, add them to the allowlist:

# .pipeguard.yml
trusted_publishers:
  - my-org           # suppresses all warnings for my-org/*
  - some-vendor      # suppresses all warnings for some-vendor/*

trusted_actions:
  - other-org/specific-action  # suppresses warning for this exact action only
  • trusted_publishers matches as a prefix — every action from my-org/* is considered trusted.
  • trusted_actions requires an exact match on the action name (without the @ref).
  • A trailing / in publisher names is optional; PipeGuard normalises it automatically.

The built-in allowlist (GitHub, AWS, Azure, Google, Docker, HashiCorp, etc.) is always active and cannot be removed.


CI integration

Add pipeguard as a pre-push check or CI step:

# .github/workflows/pipeguard.yml
- name: Scan workflows
  run: |
    pip install pipeguard-cli
    pipeguard scan .github/workflows/

Or as a pre-commit hook (.pre-commit-config.yaml):

repos:
  - repo: local
    hooks:
      - id: pipeguard
        name: PipeGuard workflow scan
        entry: pipeguard scan
        language: python
        additional_dependencies: [pipeguard-cli]
        files: \.github/workflows/.*\.ya?ml$

Output formats

Terminal (default) — human-readable table with rule, location, and fix suggestions.

JSON — machine-readable, one object per finding:

[
  {
    "rule": "cve-cve-2025-30066",
    "severity": "error",
    "message": "Action 'tj-actions/changed-files@v35' is affected by CVE-2025-30066: ...",
    "file": ".github/workflows/ci.yml",
    "line": 12,
    "fix_suggestion": "Immediately pin 'tj-actions/changed-files' to a verified safe SHA."
  }
]

SARIF — compatible with GitHub Code Scanning.


License

Apache 2.0 — see LICENSE.

Status

In active development. All Free-tier scanners are functional. Planned: auto-fix PRs (Pro), Maintainer Trust Score (Pro), cloud sandbox testing, IDE plugin.

Free-tier checks: SHA-pinning, CVE database, permissions audit (incl. id-token: write without OIDC), secrets-leak detection, action inventory, actionlint syntax checks.

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_cli-0.1.1.tar.gz (319.7 kB view details)

Uploaded Source

Built Distribution

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

pipeguard_cli-0.1.1-py3-none-any.whl (30.5 kB view details)

Uploaded Python 3

File details

Details for the file pipeguard_cli-0.1.1.tar.gz.

File metadata

  • Download URL: pipeguard_cli-0.1.1.tar.gz
  • Upload date:
  • Size: 319.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pipeguard_cli-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d6955b7162cef95ce033e2bb569d797480ccf4194627de88a9d24b5a37befaff
MD5 e8784297be1f332e144ebbb3aaafb083
BLAKE2b-256 082bb4c30059602815678dbbe5efd3bd49b7f98e294600af8431220420c4e2e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pipeguard_cli-0.1.1.tar.gz:

Publisher: deploy.yml on alex-jung/pipeguard-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pipeguard_cli-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: pipeguard_cli-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 30.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for pipeguard_cli-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1347c63b2ffbb6271932bc0714b9ff2d783287ec4ac5f1dde19d41d6ae6fe31d
MD5 031a9286c81d22576c8f095ecdca313c
BLAKE2b-256 3e77d959e5232e15d4f6876e3cc4fe33cfd59071770753301c73a7b2891af572

See more details on using hashes here.

Provenance

The following attestation bundles were made for pipeguard_cli-0.1.1-py3-none-any.whl:

Publisher: deploy.yml on alex-jung/pipeguard-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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