
CI/CD Threat Modelling
A practical threat-modelling framework for CI/CD pipelines built from two years of hardening CI/CD configurations. It walks through pipeline-level questions (who can trigger workflows, who can modify workflow definitions) and per-step questions (inputs, branch protection bypass, exposed secrets/OIDC credentials, arbitrary code execution via workflow steps, third-party dependency trust), and gives concrete GitHub Actions examples such as PR-title injection turning into arbitrary code execution and using workflow-exposed VCS credentials to self-approve a PR.
What it is
A CI/CD threat-modelling framework from a practitioner who spent ~2 years hardening CI/CD configs. It is a question-driven checklist, not a tool or vulnerability, structured to be applied end-to-end across a pipeline. GitHub Actions is used for concrete examples but the model is generic.
How it works
Two "table stakes" are assumed before the framework applies, and are worth surfacing because the summary omits them:
- Ephemeral, locked-down runners. Persistent/long-lived runners are treated as a major liability — reliably isolating runs on them is called near-impossible — and are explicitly out of scope.
- VCS credentials are assumed already configured via the platform's recommended secure mechanism.
The framework then asks questions at two levels. At the whole-pipeline level: what triggers the workflow, can it be triggered manually or from unprotected (unreviewed) branches, and where the workflow definition lives. The key insight: in GitHub Actions the workflow definition comes from the branch being executed, so anyone with write access to that branch can modify it — and whoever controls the workflow has full access to its secrets.
Per step, ask about: inputs (branch/tag names and PR titles are attacker-controllable inputs), branch protection (and who can bypass it), secrets (scope of access, long-lived vs short-lived/OIDC), workflow code (unit tests execute arbitrary repo code by default), and third-party dependencies.
What to do
Apply the per-step questions to build threat scenarios specific to your config. Concrete guardrails the page states:
- Pin third-party dependencies to a specific hash to limit impact if a dependency is compromised.
- Treat any secret reachable by a controllable workflow as fully exposed.
- Don't assume OIDC/short-lived credentials are safe — they only narrow the exposure window, not the possibility of compromise.
- Watch for injection:
echo "${{ github.event.pull_request.title }}"can become arbitrary code execution.
One named attack chain worth modelling explicitly:
flowchart TD
A[Write access to unprotected branch] --> B[Modify workflow definition]
B --> C[Workflow runs with VCS credentials]
C --> D{VCS creds can bypass<br/>branch protection?}
D -->|yes| E[Approve own PR / merge]
D -->|no| F[Blocked]The author notes VCS credentials may hold permissions "not normally available," such as bypassing branch protection — so a developer can modify the workflow to use those creds to approve their own PR.
Caveats
This is a methodology, not a fix: it produces threat scenarios, it does not remediate them. It intentionally scopes to CI/CD pipelines only and excludes broader product security. Its value depends on being run by engineers who intimately know the specific configuration.
Technologies named here
Techniques named here
- Workflow trigger abuse
- Workflow definition tampering
- Untrusted input injection
- Branch protection bypass
- Third-party dependency compromise
- Arbitrary code execution via test/build steps
Related in DevSecOps
JFrog: The Governance Gap Between Your Policy and Your Pipeline

Dev Machine Guard Now Supports Windows - StepSecurity

Socket: TanStack npm Packages Compromised
