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

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
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

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.0.tar.gz (312.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.0-py3-none-any.whl (29.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pipeguard_cli-0.1.0.tar.gz
  • Upload date:
  • Size: 312.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.0.tar.gz
Algorithm Hash digest
SHA256 d159f576be65c25ba1724c284c789d144c786032dc3be970108f04723c499969
MD5 5307f31569066120833a64ad5a6a536e
BLAKE2b-256 f85b144eba379f32610a45245e4b7fb613a8e92b4416cbb6468af5bc8b30fc78

See more details on using hashes here.

Provenance

The following attestation bundles were made for pipeguard_cli-0.1.0.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.0-py3-none-any.whl.

File metadata

  • Download URL: pipeguard_cli-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 29.0 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 12db9b59899c8dfe38b5d4e307bed532b1cff830d78df32a382844da52cd5076
MD5 4c30d1fae10bcb196339f360b68ee4a7
BLAKE2b-256 fb26d2884484bba70352d4edd542f4222b9a969462d27ee8bf8816c8b614d781

See more details on using hashes here.

Provenance

The following attestation bundles were made for pipeguard_cli-0.1.0-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