Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.pipefort.com/llms.txt

Use this file to discover all available pages before exploring further.

FieldValue
CategoryCICD-SEC-2
SeverityMEDIUM
OWASPCICD-SEC-2: Inadequate Identity and Access Management
Auto-fix

What the check does

Flags any workflow that authenticates with a secret whose name implies a long-lived personal access token. The check walks every env: block (workflow, job, step) and every step with: input, looking for ${{ secrets.NAME }} references where NAME matches any of:
  • *_PAT or PAT_*
  • *_PERSONAL_ACCESS_TOKEN (any casing or separator)
  • *_GH_TOKEN / *_GH_PAT / *_GITHUB_PAT
The literal GITHUB_TOKEN is not flagged — that’s the short-lived per-run token GitHub mints automatically, which is the recommended replacement.

Why it matters

A PAT is a static credential bound to a single human account. It:
  • Survives employee turnover (until someone notices and revokes it manually).
  • Carries the user’s full set of repo permissions, not the workflow’s least-privilege scope.
  • Is difficult to rotate — every workflow that references it must be updated together.
  • Bypasses GitHub App / organisation governance because it acts as the user.
A compromise of one PAT (phishing, leaked dotfile, third-party breach) gives an attacker the same access the user has — typically across many repos.

Vulnerable example

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
        with:
          token: ${{ secrets.RELEASE_PERSONAL_ACCESS_TOKEN }}  # ← long-lived PAT
      - run: gh release create v1.0.0
        env:
          GH_TOKEN: ${{ secrets.MY_GH_PAT }}                  # ← long-lived PAT

Safe alternatives

Use the per-run GITHUB_TOKEN with explicit permissions:
permissions:
  contents: write
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
      - run: gh release create v1.0.0
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
For cross-repo writes, install a GitHub App and mint an installation token at job start. App tokens are short-lived (1 hour) and scoped to the installation, not to any human account. For cloud-provider auth, federate via OIDC. aws-actions/configure-aws-credentials, google-github-actions/auth, and azure/login all accept the workflow’s OIDC token in place of a long-lived access key.