Skip to main content
The CLI is a single static binary and exits non-zero on findings above a threshold, so it drops straight into any CI step.

GitHub Action

The quickest path is the official Pipefort Action, which runs the scanner in a container — no install step:
name: pipefort

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  scan:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
      - uses: raphabot/pipefort@v0.1.0
        with:
          path: .
          ruleset: owasp
          fail-on: HIGH
          output: console
InputDefaultDescription
path.Path to scan for workflow files.
rulesetallall, owasp, slsa, or a specific level (e.g. slsa-build-l3).
fail-onMEDIUMFail the job at or above this severity: HIGH/MEDIUM/LOW/INFO/NONE.
outputsarifsarif, json, or console.
sarif-filepipefort.sarifWhere the SARIF report is written (when output: sarif).
github-tokenthe workflow tokenToken for the online supply-chain pin audits (known-vulnerable, impostor-commit, ref/version-mismatch, typosquat). They run automatically with the default token; set github-token: '' for a fully offline scan.
To publish findings to the Security → Code scanning tab, leave output at its sarif default and add an upload step — see SARIF for GitHub code scanning below.

Manual install (without the Action)

If you’d rather not use a container action, install the released binary directly:
      - name: Install scanner
        run: |
          curl -sSL -o pipefort.tar.gz \
            https://github.com/raphabot/pipefort/releases/latest/download/pipefort_$(curl -s https://api.github.com/repos/raphabot/pipefort/releases/latest | grep tag_name | cut -d'"' -f4)_linux_amd64.tar.gz
          tar -xzf pipefort.tar.gz
          sudo mv pipefort /usr/local/bin/

      - name: Scan workflows
        run: pipefort -p . -s HIGH -r owasp
        env:
          GITHUB_TOKEN: ${{ github.token }}  # enables the online pin audits
A few things worth calling out:
  • -s HIGH — only fail the build on HIGH findings. Start strict-but-quiet, then tighten to MEDIUM once the baseline is clean.
  • -r owasp — keep the gate focused on the five OWASP categories; treat the three best-practice checks as advisory until you’re ready to enforce them.
  • permissions: contents: read — this scanner job itself follows CICD-SEC-5. It only reads code.
  • timeout-minutes: 5 — follows BEST-PRAC-2.
For reproducible builds, pin a specific version (e.g. download/v0.1.0/pipefort_v0.1.0_linux_amd64.tar.gz) rather than latest.

SARIF for GitHub code scanning

Emit SARIF 2.1.0 with -o sarif and upload it with github/codeql-action/upload-sarif. Findings then show up in the repo’s Security → Code scanning tab and as inline annotations on pull requests — the same surface zizmor, poutine, and OpenSSF Scorecard integrate with. Each result carries a stable partialFingerprints entry (pipefort/v1) built from the rule, file, and finding content — not line numbers — so code scanning tracks a finding across commits instead of closing and reopening it whenever unrelated edits shift it down the file. It’s the same identity the web app’s triage uses.
name: pipefort

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read
  security-events: write  # required to upload SARIF

jobs:
  scan:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v4

      - name: Scan workflows (SARIF)
        run: pipefort -p . -o sarif -s NONE > pipefort.sarif

      - name: Upload to code scanning
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: pipefort.sarif
Use -s NONE on the scan step so a finding doesn’t fail the job before the SARIF is uploaded — let the Code scanning alerts (or a separate gating step) enforce policy. Severities map to SARIF levels as HIGH→error, MEDIUM→warning, and LOW/INFOnote, and each result carries a security-severity score so GitHub sorts them correctly. Toxic combinations (“Attacker Mind”) have no SARIF analog and are omitted from this format — use -o json for the complete envelope.
The same SARIF export is available from the web app on a repository’s page (Export → Download SARIF).

JSON output for downstream tooling

Pipe to jq for custom policy:
      - name: Scan workflows (JSON)
        run: pipefort -p . -o json -s NONE > findings.json

      - uses: actions/upload-artifact@v4
        with:
          name: pipefort-findings
          path: findings.json
-s NONE keeps the step from failing so the artifact is always uploaded; gate separately on the JSON content with jq if you want richer policy.

Pre-commit hook

Pipefort ships a pre-commit hook. Add it to your .pre-commit-config.yaml:
repos:
  - repo: https://github.com/raphabot/pipefort
    rev: v0.1.0
    hooks:
      - id: pipefort
The hook builds the Go CLI and scans the repo’s GitHub Actions and GitLab CI workflow files on every commit. The scanner is fast enough (sub-second on most repos) to run inline. Prefer a raw git hook? A one-liner works too:
# .git/hooks/pre-commit
#!/usr/bin/env bash
set -e
pipefort -p . -s HIGH -r owasp