How To Secure GitHub Actions

GitHub Actions democratized CI/CD. Any developer can ship a workflow file and get automated deployments running in minutes. That accessibility is also what makes it dangerous, the same low-friction that makes Actions easy to adopt makes it easy to build pipelines that are effectively high-privilege execution environments with weak access controls. The hidden tension is that most organizations tr…

GITHUB_TOKEN Has Too Much Scope By Default

Every GitHub Actions workflow receives a GITHUB_TOKEN automatically, a short-lived credential scoped to the repository with permissions to read code, write to packages, create releases, and more depending on the workflow trigger. The default permission set is broader than most workflows need. A workflow that runs tests and reports status only needs 'contents: read' and 'statuses: write.' Giving it the default broad permissions means a compromise of that workflow can do far more damage. The corr

OIDC Federation Eliminates Long-Lived Cloud Credentials

The old pattern for deploying to AWS from GitHub Actions was to store AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as repository secrets and inject them as environment variables in the workflow. Those are long-lived credentials that never expire, can't be scoped to specific repositories, and if rotated incorrectly, break deployments across multiple workflows simultaneously. They're also stored in GitHub's secrets backend, which is a single point of compromise. OIDC (OpenID Connect) federation re

Third-Party Actions Are Supply Chain Risks

The GitHub Actions marketplace has thousands of actions. They're convenient, one line to set up Node, authenticate to AWS, push a Docker image. They're also third-party code running in your pipeline with access to your secrets, your GITHUB_TOKEN, and your deployment credentials. When you reference an action as 'actions/checkout@v4', you're trusting that the 'v4' tag hasn't been moved to malicious code since you last reviewed it. Tags are mutable. That trust is misplaced. The correct practice is

Frequently asked questions

How do you handle secrets that need to be shared across multiple repositories?
GitHub organization secrets are the first-party solution, they're available to all repositories in the org or a specified subset. For more granular control, a centralized secrets manager (HashiCorp Vault, AWS Secrets Manager) accessed via OIDC federation is the right architecture. Each workflow authenticates to Vault using its OIDC token, Vault va…
How do you audit what actions are being used across all workflows in an org?
GitHub doesn't give you a first-party view of this at org scale. You need to script it: use the GitHub API to enumerate all repositories, fetch workflow files from each, and parse the 'uses:' directives. Tools like 'zizmor' can help. What you're looking for: unpinned third-party actions, actions from unknown publishers, actions with access to sens…
What's the blast radius if a GitHub Actions runner is compromised?
GitHub-hosted runners are ephemeral, each job gets a fresh VM that's destroyed after the job completes. A compromised runner can exfiltrate secrets available in that job's environment and use the GITHUB_TOKEN during the job's lifetime, but can't persist across jobs or affect other workflows. Self-hosted runners are a different story, they're persi…
Is there a way to enforce security policies across all workflows in an organization?
GitHub's required workflows feature (available on GitHub Enterprise) lets you designate specific workflows that must pass on all repositories in the org before a PR can be merged. You can use this to enforce security scanning, a centrally-managed workflow that runs Checkov, secret scanning, or license compliance, that every team must pass. For per…

Related concepts

Related articles

Recommended learning paths