# GitHub and CI/CD security: keep untrusted changes away from deployment authority

Canonical: https://www.web3sec.news/blog/github-ci-security-runbook
Author: Raiders (https://www.web3sec.news/about)
Format: guide
Topic: GitHub & CI/CD
Published: 2026-11-08
Updated: 2026-11-08

A review procedure for workflow triggers, action revisions, runner isolation and cloud deployment identity.

### Diagram: Trust the release path, not only the source.

Protect the chain from reviewed change to the artifact receiving traffic.

![Protected source enters a least-privilege release workflow, produces a digest-identified artifact, and reaches production only after artifact verification. Untrusted pull requests use isolated checks without release credentials or write access.](https://www.web3sec.news/diagrams/software-release-trust.svg)

[Full-size SVG](https://www.web3sec.news/diagrams/software-release-trust.svg) · [PNG download](https://www.web3sec.news/diagrams/software-release-trust.png)

Original explanatory control model; not a reconstruction of private incident evidence.

## Draw the path from contributor to production

Make the repository owner and deployment owner jointly accountable for the workflow inventory. For every workflow, record its trigger, checked-out revision, executable inputs, token permissions, secrets, runner and published artifacts. Include reusable workflows and scripts called indirectly. A job named lint or documentation can still execute contributor-controlled code and therefore deserves the same trust-boundary review as a build job.

Separate ordinary validation from release authorization. Identify when a public pull request, issue body, branch name or downloaded artifact enters a command or privileged job. GitHub’s secure-use guidance highlights untrusted code checkout and third-party actions. Our procedure is to trace the actual data flow rather than assume that an apparently safe event name makes the job safe.

## Reduce persistent and ambient authority

Start workflow permissions at the minimum and grant narrowly defined exceptions per job. Pin external actions to reviewed full commit revisions and inspect the code they execute, including dependencies. Do not interpolate untrusted expressions directly into shell programs. Pass data through a safe input boundary and validate its intended format before allowing it to influence a privileged operation.

Use workload identity where supported, and configure the cloud trust policy to match the intended repository, environment and other relevant claims. GitHub documents OIDC as a way to exchange workflow identity for short-lived cloud credentials. The important control is the restriction on who may obtain what role; replacing a static key with a broadly trusted OIDC role does not remove excessive privilege.

## Contain runner and artifact compromise

Treat self-hosted runners as machines that execute hostile code unless their inputs are tightly controlled. Avoid reusing a sensitive deployment runner for untrusted pull requests. Isolate credentials, workspaces and network access, and prefer an ephemeral lifecycle for jobs crossing a low-trust boundary. Review caches and artifacts as inputs whose contents can be changed, not as automatically trustworthy products of CI.

If a malicious action or job ran, identify the exact revision and authority available during that run. Preserve restricted copies of useful logs, revoke exposed credentials and examine cloud actions, repository changes and published packages. Updating the workflow is a code fix; it does not invalidate a secret already printed into a log or copied from a runner.

## Test the negative paths before granting release access

Create a harmless test contribution containing dummy shell metacharacters in a title and a build script that attempts to access a designated test secret. Confirm that validation treats text as data and never receives release credentials. Use a non-production cloud role to prove that an unauthorized branch or environment cannot exchange an OIDC token for deployment access.

Record the result as a trust-boundary test, then repeat when triggers, reusable workflows, runner pools or deployment providers change. Review action updates through the normal change process and remove unused jobs. The release checklist should identify the tested source revision, verified artifact and deployment identity so an operator can establish what actually reached production.

## Controls to take away

- CI is a privileged execution environment, not just a test dashboard.
- Short-lived credentials still require narrow trust and permissions.
- Test untrusted contributions without exposing real release secrets.

## Work through the boundary

Local planning worksheets; they do not inspect or change accounts or environments.

- [Prepare the research environment](https://www.web3sec.news/tools/research-preflight): Check authorization, source, credentials, egress and disposal for the actual lab boundary you will use.

## Working checklist

Assign owners and record supporting evidence in your team's system.

- [ ] Inventory trigger, checkout, inputs, runner and permissions for every workflow.
- [ ] Pin and review external actions and reusable workflows.
- [ ] Separate validation from release secrets and runners.
- [ ] Restrict cloud identity exchange to the intended workflow context.
- [ ] Test hostile text, unauthorized branches and compromised-action response.

## Sources & further reading

- [GitHub: secure use of Actions](https://docs.github.com/en/actions/reference/security/secure-use)
- [GitHub: OpenID Connect for workflows](https://docs.github.com/en/actions/concepts/security/openid-connect)

Incident facts are attributed to the linked reports. Recommendations are Web3Sec's analysis.

[Research methodology](https://www.web3sec.news/methodology) · [Editorial policy](https://www.web3sec.news/editorial-policy) · [Send a correction](https://www.web3sec.news/contact)
