Configure
Secrets and environments
Keep sensitive values encrypted, scope configuration narrowly, and require deployment policy to pass before a runner is assigned or an environment secret is released.
Secrets and variables
Secrets and variables share scope resolution but have different security properties.
| Value | Use for | Visibility |
|---|---|---|
| Secret | Tokens, passwords, private keys, webhook credentials. | Encrypted with the organization workspace key, write-only in the UI/API, and added to the runner masker. |
| Variable | Hosts, feature flags, region names, non-sensitive build configuration. | Stored as non-sensitive configuration and visible to authorized organization users. |
| YAML env | Static or expression-derived configuration for a workflow, job, or step. | Part of the immutable workflow snapshot; do not put cleartext credentials here. |
Masking is not authorization
Scopes and precedence
Values merge from least to most specific. A narrower value with the same exact name overrides the broader value.
| Resolution order | Scope | Availability |
|---|---|---|
| 1 — broadest | Organization | Every eligible repository in the active organization. |
| 2 | Repository | Only jobs from the selected repository. |
| 3 — narrowest | Environment | Only a job targeting the matching repository environment after protection passes. |
Organization API_HOST=https://api.example.com
Repository API_HOST=https://api.staging.example.com
Environment API_HOST=https://api.production.example.com
Job without environment → repository value
Job targeting production → environment valueEnvironment names resolve case-insensitively within a repository. The dashboard prevents duplicate names that differ only by case.
Use values in workflow YAML
Reference stored values only through the secrets and vars contexts. Put a secret in step env when a process expects an environment variable.
name: Deploy
on:
workflow_dispatch:
inputs:
target:
type: environment
required: true
env:
NODE_ENV: production
API_HOST: ${{ vars.API_HOST }}
jobs:
deploy:
environment:
name: ${{ inputs.target }}
url: ${{ steps.release.outputs.url }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- id: release
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: |
url="$(./deploy)"
echo "url=$url" >> "$GITHUB_OUTPUT"Keep secret scope small
env for a secret needed by one command. Job-level exposure makes it available to every action and command in that job.Fork pull request behavior
Fork safety is enforced by the control plane and cannot be disabled in workflow YAML.
| Resource | Fork pull request behavior |
|---|---|
| Customer secrets | No organization, repository, or environment secrets are released. |
| Repository token | Requested write scopes are downgraded to read. |
| Cache | Existing eligible cache entries are readable; saves are disabled. |
| Environment | Protection still applies, but passing it does not restore withheld fork secrets or write permissions. |
Split trusted deployment work into a separate workflow triggered from a trusted branch or reviewed manual dispatch. Do not use a pull request job to turn untrusted fork code into a privileged deployment.
Configure environment protection
Administrators configure rules from Secrets and environments. Every configured rule must pass before admission.
- 1
Create the repository environment
Choose a name and repository. Add environment-scoped secrets or variables after the environment exists. - 2
Set the wait timer
Choose 0 through 43,200 minutes. The timer begins from the protected job request and survives restarts. - 3
Choose reviewers
Require approval and select up to six current organization members. Optionally prevent the triggering actor from self-approving. - 4
Control bypass
Prevent administrator bypass when the review requirement must be absolute. Otherwise owner/admin operators may explicitly bypass with an audited decision. - 5
Restrict refs
Allow all refs, protected refs, or selected branch/tag patterns. Selected mode requires at least one branch or tag pattern.
Rules are repository-specific
Deployment history and URLs
A job environment creates durable deployment/status history by default. The environment URL is evaluated from the job plan and can use step output when the final value becomes available.
jobs:
verify:
environment:
name: production
deployment: false
runs-on: ubuntu-latest
steps:
- run: ./verify-production.shSet deployment: false to keep environment scoping and protection while intentionally suppressing the deployment record. This is useful for verification or secret-gated maintenance jobs that do not deploy a release.

