How to Give Self-Hosted Runners Least-Privilege Cloud Credentials
A runner should carry the smallest possible cloud permissions, because any job it runs inherits them.
Prefer short-lived OIDC federation over static keys, and scope the role to only the resources CI truly needs. Never attach an admin role to a runner instance profile.
Steps
- Grant the runner an IAM role scoped to specific resources and actions.
- Prefer OIDC federation so no long-lived keys sit on the host.
- Add resource and condition constraints, not wildcard
*permissions.
Scoped IAM policy
Terminal
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::ci-artifacts-my-org/*"
}
]
}Gotchas
- An instance profile is available to every job on that host; ephemeral per-job runners limit the blast radius.
- Wildcard resources turn one leaked job into full account access.
Related guides
How to Block the Cloud Metadata Endpoint on RunnersPrevent SSRF credential theft by blocking the cloud instance metadata endpoint (169.254.169.254) from GitHub…
How to Run Ephemeral Self-Hosted RunnersConfigure self-hosted GitHub Actions runners as ephemeral with the --ephemeral flag so each runner processes…