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

# CICD-SEC-8 — repository_dispatch trigger without event-type allowlist

> Unfiltered repository_dispatch lets any holder of a repo-scoped token trigger arbitrary workflow runs.

| Field    | Value                                                                                                                                                              |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Category | `CICD-SEC-8`                                                                                                                                                       |
| Severity | **MEDIUM**                                                                                                                                                         |
| OWASP    | [CICD-SEC-8: Ungoverned Usage of 3rd Party Services](https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-08-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":

```yaml theme={null}
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

```yaml theme={null}
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

```yaml theme={null}
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](/rules/cicd-sec-4) check enforces this for the well-known PR contexts) and validate it before use.
