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-8
SeverityMEDIUM
OWASPCICD-SEC-8: Ungoverned Usage of 3rd Party Services
Auto-fix

What the check does

Flags any workflow whose on: block subscribes to repository_dispatch without declaring an explicit types: allowlist. The check passes when:
  • The workflow does not subscribe to repository_dispatch at all, or
  • The subscription declares a non-empty types: list.
It fires for the three syntactic shapes that all amount to “unfiltered”:
on: repository_dispatch                 # ← scalar
on: [push, repository_dispatch]         # ← sequence
on:
  repository_dispatch:                  # ← mapping without types:

Why it matters

repository_dispatch is GitHub’s “external system kicks off a workflow” hook. The dispatcher only needs a token with repo scope (a PAT, a fine-grained token, or a GitHub App installation token). Without types:, any caller can trigger the workflow with any event_type and any client_payload. Common consequences:
  • A third-party service you onboarded for one purpose (say, “rebuild on Sentry release”) becomes a generic build-pipeline trigger.
  • A leaked token can be used to trigger the workflow as a covert channel — for example, to run expensive jobs, exfiltrate secrets via deliberately-failing steps, or quietly poison caches.
  • The workflow’s inputs (via ${{ github.event.client_payload.* }}) are attacker-controlled JSON, often passed unchecked into shell scripts.
Pinning types: doesn’t fix the input-trust problem, but it limits the trigger surface to event types you’ve actually planned for.

Vulnerable example

on:
  repository_dispatch:        # ← any event_type fires this
jobs:
  rebuild:
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh ${{ github.event.client_payload.target }}

Safe alternative

on:
  repository_dispatch:
    types: [sentry-release]   # ← only this event_type
jobs:
  rebuild:
    runs-on: ubuntu-latest
    steps:
      - name: Validate payload
        env:
          TARGET: ${{ github.event.client_payload.target }}
        run: |
          case "$TARGET" in
            staging|production) ;;
            *) echo "Unexpected target: $TARGET"; exit 1 ;;
          esac
          ./deploy.sh "$TARGET"
Treat every value under github.event.client_payload.* as untrusted: assign it to an env var (Pipefort’s CICD-SEC-4 check enforces this for the well-known PR contexts) and validate it before use.